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

(Feature) Enable proxy for both strategies #1024

Merged
merged 16 commits into from
Jul 13, 2018
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ REACT_APP_MINTED_CAPPED_TOKEN_MANAGER_ADDRESS='{"3":"0xbcb59c250cd3b33573ac61336
REACT_APP_DUTCH_IDX_ADDRESS='{"3":"0x9e691aa80c516c7d92de3171b650c8e38ab54de5"}'
REACT_APP_DUTCH_CROWDSALE_ADDRESS='{"3":"0x5db537686cea5a252996bec21ff4755cf604574c"}'
REACT_APP_DUTCH_TOKEN_ADDRESS='{"3":"0x59068cb9a592b9f29a7ded22c5caff5d268fec72"}'
REACT_APP_TW_PROXIES_REGISTRY_ADDRESS='{"3":"0xba826663e973fe8e336ccc7acdb2691f8eed566c"}'
REACT_APP_PROXY_PROVIDER='{"3":"0x5eadd1456ce64247b48bac2e53605b4a934c53fd"}'
REACT_APP_REGISTRY_EXEC_ID='0x116fea137db6e131133e7f2bab296045d8f41cc5607279db17b218cab0929a51'
REACT_APP_MINTED_CAPPED_APP_NAME='MintedCappedCrowdsale'
REACT_APP_DUTCH_APP_NAME='DutchCrowdsale'
Expand Down
14 changes: 14 additions & 0 deletions public/contracts/DutchProxy.abi
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,20 @@
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getCrowdsaleUniqueBuyers",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
2 changes: 1 addition & 1 deletion public/contracts/DutchProxy.bin

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions public/contracts/DutchProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface IAdmin {
function getTokensSold() external view returns (uint);
function getCrowdsaleWhitelist() external view returns (uint, address[]);
function getWhitelistStatus(address) external view returns (uint, uint);
function getCrowdsaleUniqueBuyers() external view returns (uint);
}

interface AdminIdx {
Expand All @@ -22,6 +23,7 @@ interface AdminIdx {
function getTokensSold(address, bytes32) external view returns (uint);
function getCrowdsaleWhitelist(address, bytes32) external view returns (uint, address[]);
function getWhitelistStatus(address, bytes32, address) external view returns (uint, uint);
function getCrowdsaleUniqueBuyers(address, bytes32) external view returns (uint);
}

// File: contracts/classes/sale/ISale.sol
Expand Down Expand Up @@ -255,6 +257,15 @@ contract AdminProxy is IAdmin, SaleProxy {
function getWhitelistStatus(address _buyer) external view returns (uint, uint) {
return AdminIdx(app_index).getWhitelistStatus(app_storage, app_exec_id, _buyer);
}

/*
Returns the number of unique addresses that have participated in the crowdsale

@return uint: The number of unique addresses that have participated in the crowdsale
*/
function getCrowdsaleUniqueBuyers() external view returns (uint) {
return AdminIdx(app_index).getCrowdsaleUniqueBuyers(app_storage, app_exec_id);
}
}

contract TokenProxy is IToken, AdminProxy {
Expand Down
145 changes: 145 additions & 0 deletions public/contracts/ProxiesRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
pragma solidity ^0.4.24;

/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;


event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);


/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}

/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}

/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}

/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}

/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}

contract AbstractProxy {
bytes32 public app_exec_id;
function getAdmin() external view returns (address);
}

contract MintedCappedIdx {
function getAdmin(address, bytes32) external view returns (address);
}

contract DutchIdx {
function getAdmin(address, bytes32) external view returns (address);
}

/**
* Registry of contracts deployed from Token Wizard 2.0.
*/
contract TokenWizardProxiesRegistry is Ownable {
address public abstractStorageAddr;
address public mintedCappedIdxAddr;
address public dutchIdxAddr;
mapping (address => Crowdsale[]) private deployedCrowdsalesByUser;
event Added(address indexed sender, address indexed proxyAddress, bytes32 appExecID);
struct Crowdsale {
address proxyAddress;
bytes32 execID;
}

constructor (
address _abstractStorage,
address _mintedCappedIdx,
address _dutchIdx
) public {
require(_abstractStorage != address(0));
require(_mintedCappedIdx != address(0));
require(_dutchIdx != address(0));
require(_abstractStorage != _mintedCappedIdx && _abstractStorage != _dutchIdx && _mintedCappedIdx != _dutchIdx);
abstractStorageAddr = _abstractStorage;
mintedCappedIdxAddr = _mintedCappedIdx;
dutchIdxAddr = _dutchIdx;
}

function changeAbstractStorage(address newAbstractStorageAddr) public onlyOwner {
abstractStorageAddr = newAbstractStorageAddr;
}

function changeMintedCappedIdx(address newMintedCappedIdxAddr) public onlyOwner {
mintedCappedIdxAddr = newMintedCappedIdxAddr;
}

function changeDutchIdxAddr(address newDutchIdxAddr) public onlyOwner {
dutchIdxAddr = newDutchIdxAddr;
}

function trackCrowdsale(address proxyAddress) public {
AbstractProxy proxy = AbstractProxy(proxyAddress);
require(proxyAddress != address(0));
require(msg.sender == proxy.getAdmin());
bytes32 appExecID = proxy.app_exec_id();
require(mintedCappedIdx.getAdmin(abstractStorageAddr, appExecID) != address(0) || dutchIdx.getAdmin(abstractStorageAddr, appExecID) != address(0));
MintedCappedIdx mintedCappedIdx = MintedCappedIdx(mintedCappedIdxAddr);
DutchIdx dutchIdx = DutchIdx(dutchIdxAddr);
for (uint i = 0; i < deployedCrowdsalesByUser[msg.sender].length; i++) {
require(deployedCrowdsalesByUser[msg.sender][i].proxyAddress != proxyAddress);
require(deployedCrowdsalesByUser[msg.sender][i].execID != appExecID);
}
deployedCrowdsalesByUser[msg.sender].push(Crowdsale({proxyAddress: proxyAddress, execID: appExecID}));
emit Added(msg.sender, proxyAddress, appExecID);
}

function countCrowdsalesForUser(address deployer) public view returns (uint) {
return deployedCrowdsalesByUser[deployer].length;
}

function getCrowdsalesForUser(address deployer) public view returns (address[]) {
address[] storage proxies;
for (uint k = 0; k < deployedCrowdsalesByUser[deployer].length; k++) {
proxies.push(deployedCrowdsalesByUser[deployer][k].proxyAddress);
}
return proxies;
}
}
23 changes: 7 additions & 16 deletions src/components/contribute/QRPaymentProcess.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,30 @@ import React from 'react'
import QRCode from 'qrcode.react'
import { CopyToClipboard } from 'react-copy-to-clipboard'

const QRPaymentProcess = ({ registryExecAddr, txData }) => {
const QRPaymentProcess = ({ crowdsaleProxyAddr, registryExecAddr, txData }) => {
const targetContractStr = crowdsaleProxyAddr ? 'Proxy' : 'RegistryExec'
const targetAddr = crowdsaleProxyAddr ? crowdsaleProxyAddr : registryExecAddr
return (
<div>
<div className="payment-process">
<div className="payment-process-qr">
<QRCode value={registryExecAddr} />
<QRCode value={targetAddr} />
</div>
<p className="payment-process-hash">{registryExecAddr}</p>
<p className="payment-process-hash">{targetAddr}</p>

<CopyToClipboard text={registryExecAddr}>
<CopyToClipboard text={targetAddr}>
<a href="" onClick={e => e.preventDefault()} className="payment-process-copy">
Copy Address
</a>
</CopyToClipboard>

{/* <div className="payment-process-loader">Waiting for payment</div> */}
<div className="payment-process-notation">
<p className="payment-process-notation-title">Important</p>
<p className="payment-process-notation-description">
Send ethers to the Auth-os RegistryExec smart-contract address with a data: {txData}
Send ethers to the Auth-os {targetContractStr} smart-contract address with a data: {txData}
</p>
</div>
</div>
{/* <div className="payment-process">
<div className="payment-process-success"></div>
<p className="payment-process-description">
Your Project tokens were sent to
</p>
<p className="payment-process-hash">
0x6b0770d930bB22990c83fBBfcba6faB129AD7E385
</p>
<a href="#" className="payment-process-see">See it on the blockchain</a>
</div> */}
</div>
)
}
Expand Down
23 changes: 17 additions & 6 deletions src/components/contribute/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { ContributeForm } from './ContributeForm'
import { CopyToClipboard } from 'react-copy-to-clipboard'
import ReactTooltip from 'react-tooltip'
import logdown from 'logdown'
import { DEPLOYMENT_VALUES } from '../../utils/constants'

const logger = logdown('TW:contribute')

Expand Down Expand Up @@ -403,7 +404,13 @@ export class Contribute extends React.Component {
const targetContractName = execID ? 'registryExec' : crowdsaleStore.proxyName
const method = methodToExec(targetContractName, `buy()`, this.getBuyParams, paramsToExec)

const estimatedGas = await method.estimateGas(opts)
let estimatedGas
try {
estimatedGas = await method.estimateGas(opts)
} catch (e) {
console.log(e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger.error instead

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

estimatedGas = DEPLOYMENT_VALUES.GAS_REQUIRED.BUY
}
logger.log('estimatedGas:', estimatedGas)

opts.gasLimit = calculateGasLimit(estimatedGas)
Expand Down Expand Up @@ -453,7 +460,7 @@ export class Contribute extends React.Component {
const { proxyName } = crowdsaleStore

const { curAddr, contributeThrough, web3Available, toNextTick, nextTick, minimumContribution } = this.state
const crowdsaleExecID = contractStore.crowdsale && contractStore.crowdsale.execID
const crowdsaleExecID = crowdsale && crowdsale.execID
const { days, hours, minutes, seconds } = toNextTick

const { decimals, ticker, name } = tokenStore
Expand All @@ -477,13 +484,17 @@ export class Contribute extends React.Component {
//min contribution
const minimumContributionDisplay =
minimumContribution >= 0 ? `${minimumContribution} ${tokenTicker}` : 'You are not allowed'

const registryExecAddr =
contractStore.registryExec && contractStore.registryExec.addr ? contractStore.registryExec.addr : ''

const crowdsaleProxyAddr = contractStore[proxyName] && contractStore[proxyName].addr
const QRPaymentProcessElement =
contributeThrough === CONTRIBUTION_OPTIONS.QR &&
(crowdsaleExecID || (contractStore[proxyName] && contractStore[proxyName].addr)) ? (
<QRPaymentProcess registryExecAddr={registryExecAddr} txData={getExecBuyCallData(crowdsaleExecID)} />
contributeThrough === CONTRIBUTION_OPTIONS.QR && (crowdsaleExecID || crowdsaleProxyAddr) ? (
<QRPaymentProcess
crowdsaleProxyAddr={crowdsaleProxyAddr}
registryExecAddr={registryExecAddr}
txData={getExecBuyCallData(crowdsaleExecID)}
/>
) : null

const rightColumnClasses = classNames('contribute-table-cell', 'contribute-table-cell_right', {
Expand Down
35 changes: 26 additions & 9 deletions src/components/crowdsale/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,26 @@ export let getCrowdsaleData = async (initCrowdsaleContract, execID) => {
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('team_wallet')) {
crowdsaleInfo.team_wallet = crowdsaleInfo[1]
}
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_initialized')) {
crowdsaleInfo.is_initialized = crowdsaleInfo[2]
}
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_finalized')) {
crowdsaleInfo.is_finalized = crowdsaleInfo[3]
if (crowdsaleStore.isMintedCappedCrowdsale) {
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_initialized')) {
crowdsaleInfo.is_initialized = crowdsaleInfo[2]
}
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_finalized')) {
crowdsaleInfo.is_finalized = crowdsaleInfo[3]
}
} else if (crowdsaleStore.isDutchAuction) {
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_initialized')) {
crowdsaleInfo.is_initialized = crowdsaleInfo[3]
}
if (crowdsaleInfo && !crowdsaleInfo.hasOwnProperty('is_finalized')) {
crowdsaleInfo.is_finalized = crowdsaleInfo[4]
}
}
const wei_raised = crowdsaleInfo.wei_raised ? crowdsaleInfo.wei_raised : crowdsaleInfo[0]
const wei_raised = crowdsaleInfo.wei_raised
let tokensSold = await getTokensSold(...params).call()
console.log('tokensSold:', tokensSold)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger.log (I'm the logger police 👮‍♂️)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

const contributors = await getCrowdsaleUniqueBuyers(...params).call()
const { fromWei } = web3Store.web3.utils

crowdsalePageStore.setProperty('weiRaised', wei_raised)
crowdsalePageStore.setProperty('ethRaised', fromWei(wei_raised, 'ether'))
crowdsalePageStore.setProperty('tokensSold', tokensSold)
Expand All @@ -130,13 +139,19 @@ export let getCrowdsaleData = async (initCrowdsaleContract, execID) => {

if (crowdsaleStore.isDutchAuction) {
const crowdsaleStatus = await getCrowdsaleStatus(...params).call()
const { max_sellable } = await isCrowdsaleFull(...params).call()
crowdsaleStatus.start_rate = crowdsaleStatus.start_rate || crowdsaleStatus[0]
crowdsaleStatus.end_rate = crowdsaleStatus.end_rate || crowdsaleStatus[1]
crowdsaleStatus.current_rate = crowdsaleStatus.current_rate || crowdsaleStatus[2]
crowdsaleStatus.time_remaining = crowdsaleStatus.time_remaining || crowdsaleStatus[4]
const tokens_remaining = crowdsaleStatus.tokens_remaining || crowdsaleStatus[5]
const _isCrowdsaleFull = await isCrowdsaleFull(...params).call()
const max_sellable = _isCrowdsaleFull.max_sellable || _isCrowdsaleFull[1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, why in some cases you use the array lookup for the value as an alternative, and in other cases just go with the object key lookup like in?:

https://github.com/poanetwork/token-wizard/pull/1024/files#diff-5c25cfce1eba8feb7668398c93446a0bR118

const wei_raised = crowdsaleInfo.wei_raised

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the array lookup because Proxy getters return only arrays. In the line, that you provided, array lookup wasn't made because it was made earlier in this line:

crowdsaleInfo.wei_raised = crowdsaleInfo[0]

const current_rate = chooseRateForDutchAuction(crowdsaleStatus)

crowdsalePageStore.setProperty('rate', current_rate) //should be one token in wei
crowdsalePageStore.setProperty('maximumSellableTokens', max_sellable)

const tokenRemainingBN = toBigNumber(crowdsaleStatus.tokens_remaining)
const tokenRemainingBN = toBigNumber(tokens_remaining)
const curRateBN = toBigNumber(current_rate) //one token in wei
const remainingWEI = curRateBN.gt(0)
? tokenRemainingBN
Expand Down Expand Up @@ -219,6 +234,8 @@ export let getCrowdsaleTargetDates = (initCrowdsaleContract, execID) => {
.getCrowdsaleStartAndEndTimes(...params)
.call()
.then(crowdsaleStartAndEndTimes => {
crowdsaleStartAndEndTimes.start_time = crowdsaleStartAndEndTimes.start_time || crowdsaleStartAndEndTimes[0]
crowdsaleStartAndEndTimes.end_time = crowdsaleStartAndEndTimes.end_time || crowdsaleStartAndEndTimes[1]
const tierDates = setTierDates(crowdsaleStartAndEndTimes.start_time, crowdsaleStartAndEndTimes.end_time)

fillCrowdsalePageStoreDates(tierDates.startsAtMilliseconds, tierDates.endsAtMilliseconds)
Expand Down
Loading