Skip to content

Commit db8dc0e

Browse files
abarmatdavekay100
authored andcommitted
cli,staking:
- Fix visibility of _collectProtocolFees function() - Make rebate lib external - Add support to deploy libraries in the CLI script - Save library address into the address-book - Fix contract deploy command, arg was being overriden - Bump buidler version
1 parent 1846eb9 commit db8dc0e

File tree

13 files changed

+202
-109
lines changed

13 files changed

+202
-109
lines changed

buidler.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ const config = {
162162
ganache: {
163163
chainId: 1337,
164164
url: 'http://localhost:8545',
165+
gasPrice: 300000000000, // 300 gwei
165166
},
166167
},
167168
etherscan: {

cli/address-book.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type AddressBookEntry = {
1212
txHash?: string
1313
proxy?: boolean
1414
implementation?: AddressBookEntry
15+
libraries?: { [libraryName: string]: string }
1516
}
1617

1718
export type AddressBookJson = {

cli/artifacts.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'fs'
22
import { utils } from 'ethers'
3+
import { LinkReferences } from '@nomiclabs/buidler/types'
34

45
type Abi = Array<string | utils.FunctionFragment | utils.EventFragment | utils.ParamType>
56

@@ -8,6 +9,8 @@ type Artifact = {
89
abi: Abi
910
bytecode: string
1011
deployedBytecode: string
12+
linkReferences?: LinkReferences
13+
deployedLinkReferences?: LinkReferences
1114
}
1215

1316
const ARTIFACTS_PATH = './build/contracts/'

cli/commands/deploy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const deployCommand = {
2828
type: 'string',
2929
requiresArg: true,
3030
})
31-
.option('n', {
31+
.option('c', {
3232
alias: 'contract',
3333
description: 'Contract name to deploy',
3434
type: 'string',

cli/env.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@ export const loadContracts = (
2929
const contracts = {}
3030
for (const contractName of addressBook.listEntries()) {
3131
const contractEntry = addressBook.getEntry(contractName)
32-
const contract = getContractAt(contractName, contractEntry.address)
33-
contracts[contractName] = contract
34-
if (wallet) {
35-
contracts[contractName] = contracts[contractName].connect(wallet)
32+
try {
33+
const contract = getContractAt(contractName, contractEntry.address)
34+
contracts[contractName] = contract
35+
if (wallet) {
36+
contracts[contractName] = contracts[contractName].connect(wallet)
37+
}
38+
} catch (err) {
39+
logger.warn(`Could not load contract ${contractName} - ${err.message}`)
3640
}
3741
}
3842
return contracts

cli/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as network from './network'
2+
3+
export { network }

cli/network.ts

Lines changed: 108 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { providers, utils, Contract, ContractFactory, ContractTransaction, Wallet } from 'ethers'
1+
import { LinkReferences } from '@nomiclabs/buidler/types'
2+
3+
import { providers, utils, Contract, ContractFactory, ContractTransaction, Signer } from 'ethers'
24
import consola from 'consola'
35

46
import { AddressBook } from './address-book'
@@ -11,6 +13,14 @@ const logger = consola.create({})
1113

1214
const hash = (input: string): string => keccak256(`0x${input.replace(/^0x/, '')}`)
1315

16+
type DeployResult = {
17+
contract: Contract
18+
creationCodeHash: string
19+
runtimeCodeHash: string
20+
txHash: string
21+
libraries?: { [libraryName: string]: string }
22+
}
23+
1424
// Simple sanity checks to make sure contracts from our address book have been deployed
1525
export const isContractDeployed = async (
1626
name: string,
@@ -55,7 +65,7 @@ export const isContractDeployed = async (
5565
}
5666

5767
export const sendTransaction = async (
58-
wallet: Wallet,
68+
sender: Signer,
5969
contract: Contract,
6070
fn: string,
6171
...params
@@ -79,8 +89,8 @@ export const sendTransaction = async (
7989
}
8090
logger.log(`> Sent transaction ${fn}: ${params}, txHash: ${tx.hash}`)
8191
// Wait for transaction to be mined
82-
const receipt = await wallet.provider.waitForTransaction(tx.hash)
83-
const networkName = (await wallet.provider.getNetwork()).name
92+
const receipt = await sender.provider.waitForTransaction(tx.hash)
93+
const networkName = (await sender.provider.getNetwork()).name
8494
if (networkName === 'kovan' || networkName === 'rinkeby') {
8595
logger.success(`Transaction mined 'https://${networkName}.etherscan.io/tx/${tx.hash}'`)
8696
} else {
@@ -89,73 +99,109 @@ export const sendTransaction = async (
8999
return receipt
90100
}
91101

92-
export const getContractFactory = (name: string): ContractFactory => {
102+
export const getContractFactory = (
103+
name: string,
104+
libraries?: { [libraryName: string]: string },
105+
): ContractFactory => {
93106
const artifact = loadArtifact(name)
94-
return ContractFactory.fromSolidity(artifact)
107+
// Fixup libraries
108+
if (libraries && Object.keys(libraries).length > 0) {
109+
artifact.bytecode = linkLibraries(artifact, libraries)
110+
}
111+
return new ContractFactory(artifact.abi, artifact.bytecode)
95112
}
96113

97114
export const getContractAt = (name: string, address: string): Contract => {
98-
return getContractFactory(name).attach(address)
115+
const artifact = loadArtifact(name)
116+
return new Contract(address, artifact.abi)
99117
}
100118

101119
export const deployContract = async (
102120
name: string,
103121
args: Array<string>,
104-
wallet: Wallet,
105-
): Promise<Contract> => {
106-
const factory = getContractFactory(name)
122+
sender: Signer,
123+
autolink = true,
124+
silent = false,
125+
): Promise<DeployResult> => {
126+
// This function will autolink, that means it will automatically deploy external libraries
127+
// and link them to the contract
128+
const libraries = {}
129+
if (autolink) {
130+
const artifact = loadArtifact(name)
131+
if (artifact.linkReferences && Object.keys(artifact.linkReferences).length > 0) {
132+
for (const fileReferences of Object.values(artifact.linkReferences)) {
133+
for (const libName of Object.keys(fileReferences)) {
134+
const deployResult = await deployContract(libName, [], sender, false, silent)
135+
libraries[libName] = deployResult.contract.address
136+
}
137+
}
138+
}
139+
}
107140

108-
const contract = await factory.connect(wallet).deploy(...args)
141+
// Deploy
142+
const factory = getContractFactory(name, libraries)
143+
const contract = await factory.connect(sender).deploy(...args)
109144
const txHash = contract.deployTransaction.hash
110-
logger.log(`> Deploy ${name}, txHash: ${txHash}`)
111-
await wallet.provider.waitForTransaction(txHash)
145+
if (!silent) {
146+
logger.log(`> Deploy ${name}, txHash: ${txHash}`)
147+
}
148+
await sender.provider.waitForTransaction(txHash)
112149

113-
logger.log('= CreationCodeHash: ', hash(factory.bytecode))
114-
logger.log('= RuntimeCodeHash: ', hash(await wallet.provider.getCode(contract.address)))
115-
logger.success(`${name} has been deployed to address: ${contract.address}`)
150+
// Receipt
151+
const creationCodeHash = hash(factory.bytecode)
152+
const runtimeCodeHash = hash(await sender.provider.getCode(contract.address))
153+
if (!silent) {
154+
logger.log('= CreationCodeHash: ', creationCodeHash)
155+
logger.log('= RuntimeCodeHash: ', runtimeCodeHash)
156+
logger.success(`${name} has been deployed to address: ${contract.address}`)
157+
}
116158

117-
return contract
159+
return { contract, creationCodeHash, runtimeCodeHash, txHash, libraries }
118160
}
119161

120162
export const deployContractAndSave = async (
121163
name: string,
122164
args: Array<{ name: string; value: string }>,
123-
wallet: Wallet,
165+
sender: Signer,
124166
addressBook: AddressBook,
125167
): Promise<Contract> => {
126168
// Deploy the contract
127-
const contract = await deployContract(
169+
const deployResult = await deployContract(
128170
name,
129171
args.map((a) => a.value),
130-
wallet,
172+
sender,
131173
)
132174

133175
// Save address entry
134-
const artifact = loadArtifact(name)
135176
addressBook.setEntry(name, {
136-
address: contract.address,
177+
address: deployResult.contract.address,
137178
constructorArgs: args.length === 0 ? undefined : args,
138-
creationCodeHash: hash(artifact.bytecode),
139-
runtimeCodeHash: hash(await wallet.provider.getCode(contract.address)),
140-
txHash: contract.deployTransaction.hash,
179+
creationCodeHash: deployResult.creationCodeHash,
180+
runtimeCodeHash: deployResult.runtimeCodeHash,
181+
txHash: deployResult.txHash,
182+
libraries:
183+
deployResult.libraries && Object.keys(deployResult.libraries).length > 0
184+
? deployResult.libraries
185+
: undefined,
141186
})
142187

143-
return contract
188+
return deployResult.contract
144189
}
145190

146191
export const deployContractWithProxyAndSave = async (
147192
name: string,
148193
args: Array<{ name: string; value: string }>,
149-
wallet: Wallet,
194+
sender: Signer,
150195
addressBook: AddressBook,
151196
): Promise<Contract> => {
152197
// Deploy implementation
153-
const contract = await deployContractAndSave(name, [], wallet, addressBook)
198+
const contract = await deployContractAndSave(name, [], sender, addressBook)
154199
// Deploy proxy
155-
const proxy = await deployContract('GraphProxy', [contract.address], wallet)
200+
const deployResult = await deployContract('GraphProxy', [contract.address], sender)
201+
const proxy = deployResult.contract
156202
// Implementation accepts upgrade
157203
await sendTransaction(
158-
wallet,
204+
sender,
159205
contract,
160206
'acceptProxy',
161207
...[proxy.address, ...args.map((a) => a.value)],
@@ -168,7 +214,7 @@ export const deployContractWithProxyAndSave = async (
168214
address: proxy.address,
169215
initArgs: args.length === 0 ? undefined : args,
170216
creationCodeHash: hash(artifact.bytecode),
171-
runtimeCodeHash: hash(await wallet.provider.getCode(proxy.address)),
217+
runtimeCodeHash: hash(await sender.provider.getCode(proxy.address)),
172218
txHash: proxy.deployTransaction.hash,
173219
proxy: true,
174220
implementation: contractEntry,
@@ -177,3 +223,34 @@ export const deployContractWithProxyAndSave = async (
177223
// Use interface of contract but with the proxy address
178224
return contract.attach(proxy.address)
179225
}
226+
227+
export const linkLibraries = (
228+
artifact: {
229+
bytecode: string
230+
linkReferences?: LinkReferences
231+
},
232+
libraries?: { [libraryName: string]: string },
233+
): string => {
234+
let bytecode = artifact.bytecode
235+
236+
if (libraries) {
237+
if (artifact.linkReferences) {
238+
for (const [fileName, fileReferences] of Object.entries(artifact.linkReferences)) {
239+
for (const [libName, fixups] of Object.entries(fileReferences)) {
240+
const addr = libraries[libName]
241+
if (addr === undefined) {
242+
continue
243+
}
244+
245+
for (const fixup of fixups) {
246+
bytecode =
247+
bytecode.substr(0, 2 + fixup.start * 2) +
248+
addr.substr(2) +
249+
bytecode.substr(2 + (fixup.start + fixup.length) * 2)
250+
}
251+
}
252+
}
253+
}
254+
}
255+
return bytecode
256+
}

contracts/staking/Staking.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
12621262
* @param _tokens Total tokens received used to calculate the amount of fees to collect
12631263
* @return Amount of protocol fees
12641264
*/
1265-
function _collectProtocolFees(uint256 _tokens) internal returns (uint256) {
1265+
function _collectProtocolFees(uint256 _tokens) internal view returns (uint256) {
12661266
if (protocolPercentage == 0) {
12671267
return 0;
12681268
}

contracts/staking/libs/Cobbs.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ library LibCobbDouglas {
4646
uint256 totalStake,
4747
uint32 alphaNumerator,
4848
uint32 alphaDenominator
49-
) internal pure returns (uint256 rewards) {
49+
) public pure returns (uint256 rewards) {
5050
int256 feeRatio = LibFixedMath.toFixed(fees, totalFees);
5151
int256 stakeRatio = LibFixedMath.toFixed(stake, totalStake);
5252
if (feeRatio == 0 || stakeRatio == 0) {

contracts/staking/libs/Rebates.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ library Rebates {
9292
);
9393

9494
// Under NO circumstance we will reward more than total fees in the pool
95-
uint256 unclaimedFees = pool.fees.sub(pool.claimedRewards);
96-
if (rebateReward > unclaimedFees) {
97-
rebateReward = unclaimedFees;
95+
uint256 _unclaimedFees = pool.fees.sub(pool.claimedRewards);
96+
if (rebateReward > _unclaimedFees) {
97+
rebateReward = _unclaimedFees;
9898
}
9999

100100
// Update pool state

0 commit comments

Comments
 (0)