Update docs

This commit is contained in:
github-actions
2022-04-26 16:51:43 +00:00
parent d75a9e5480
commit 84526a0944
151 changed files with 17094 additions and 11955 deletions

View File

@ -0,0 +1,63 @@
const { promisify } = require('util');
const BridgeAMBMock = artifacts.require('BridgeAMBMock');
const BridgeArbitrumL1Mock = artifacts.require('BridgeArbitrumL1Mock');
const BridgeArbitrumL2Mock = artifacts.require('BridgeArbitrumL2Mock');
const BridgeOptimismMock = artifacts.require('BridgeOptimismMock');
const BridgePolygonChildMock = artifacts.require('BridgePolygonChildMock');
class BridgeHelper {
static async deploy (type) {
return new BridgeHelper(await deployBridge(type));
}
constructor (bridge) {
this.bridge = bridge;
this.address = bridge.address;
}
call (from, target, selector = undefined, args = []) {
return this.bridge.relayAs(
target.address || target,
selector
? target.contract.methods[selector](...args).encodeABI()
: '0x',
from,
);
}
}
async function deployBridge (type = 'Arbitrum-L2') {
switch (type) {
case 'AMB':
return BridgeAMBMock.new();
case 'Arbitrum-L1':
return BridgeArbitrumL1Mock.new();
case 'Arbitrum-L2': {
const instance = await BridgeArbitrumL2Mock.new();
const code = await web3.eth.getCode(instance.address);
await promisify(web3.currentProvider.send.bind(web3.currentProvider))({
jsonrpc: '2.0',
method: 'hardhat_setCode',
params: [ '0x0000000000000000000000000000000000000064', code ],
id: new Date().getTime(),
});
return BridgeArbitrumL2Mock.at('0x0000000000000000000000000000000000000064');
}
case 'Optimism':
return BridgeOptimismMock.new();
case 'Polygon-Child':
return BridgePolygonChildMock.new();
default:
throw new Error(`CrossChain: ${type} is not supported`);
}
}
module.exports = {
BridgeHelper,
};

View File

@ -0,0 +1,24 @@
const { config } = require('hardhat');
const optimizationsEnabled = config.solidity.compilers.some(c => c.settings.optimizer.enabled);
/** Revert handler that supports custom errors. */
async function expectRevertCustomError (promise, reason) {
try {
await promise;
expect.fail('Expected promise to throw but it didn\'t');
} catch (revert) {
if (reason) {
if (optimizationsEnabled) {
// Optimizations currently mess with Hardhat's decoding of custom errors
expect(revert.message).to.include.oneOf([reason, 'unrecognized return data or custom error']);
} else {
expect(revert.message).to.include(reason);
}
}
}
};
module.exports = {
expectRevertCustomError,
};

211
test/helpers/governance.js Normal file
View File

@ -0,0 +1,211 @@
const { time } = require('@openzeppelin/test-helpers');
function zip (...args) {
return Array(Math.max(...args.map(array => array.length)))
.fill()
.map((_, i) => args.map(array => array[i]));
}
function concatHex (...args) {
return web3.utils.bytesToHex([].concat(...args.map(h => web3.utils.hexToBytes(h || '0x'))));
}
function concatOpts (args, opts = null) {
return opts ? args.concat(opts) : args;
}
class GovernorHelper {
constructor (governor) {
this.governor = governor;
}
delegate (delegation = {}, opts = null) {
return Promise.all([
delegation.token.delegate(delegation.to, { from: delegation.to }),
delegation.value &&
delegation.token.transfer(...concatOpts([ delegation.to, delegation.value ]), opts),
delegation.tokenId &&
delegation.token.ownerOf(delegation.tokenId).then(owner =>
delegation.token.transferFrom(...concatOpts([ owner, delegation.to, delegation.tokenId ], opts)),
),
]);
}
propose (opts = null) {
const proposal = this.currentProposal;
return this.governor.methods[
proposal.useCompatibilityInterface
? 'propose(address[],uint256[],string[],bytes[],string)'
: 'propose(address[],uint256[],bytes[],string)'
](...concatOpts(proposal.fullProposal, opts));
}
queue (opts = null) {
const proposal = this.currentProposal;
return proposal.useCompatibilityInterface
? this.governor.methods['queue(uint256)'](...concatOpts(
[ proposal.id ],
opts,
))
: this.governor.methods['queue(address[],uint256[],bytes[],bytes32)'](...concatOpts(
proposal.shortProposal,
opts,
));
}
execute (opts = null) {
const proposal = this.currentProposal;
return proposal.useCompatibilityInterface
? this.governor.methods['execute(uint256)'](...concatOpts(
[ proposal.id ],
opts,
))
: this.governor.methods['execute(address[],uint256[],bytes[],bytes32)'](...concatOpts(
proposal.shortProposal,
opts,
));
}
cancel (opts = null) {
const proposal = this.currentProposal;
return proposal.useCompatibilityInterface
? this.governor.methods['cancel(uint256)'](...concatOpts(
[ proposal.id ],
opts,
))
: this.governor.methods['cancel(address[],uint256[],bytes[],bytes32)'](...concatOpts(
proposal.shortProposal,
opts,
));
}
vote (vote = {}, opts = null) {
const proposal = this.currentProposal;
return vote.signature
// if signature, and either params or reason →
? vote.params || vote.reason
? vote.signature({
proposalId: proposal.id,
support: vote.support,
reason: vote.reason || '',
params: vote.params || '',
}).then(({ v, r, s }) => this.governor.castVoteWithReasonAndParamsBySig(...concatOpts(
[ proposal.id, vote.support, vote.reason || '', vote.params || '', v, r, s ],
opts,
)))
: vote.signature({
proposalId: proposal.id,
support: vote.support,
}).then(({ v, r, s }) => this.governor.castVoteBySig(...concatOpts(
[ proposal.id, vote.support, v, r, s ],
opts,
)))
: vote.params
// otherwise if params
? this.governor.castVoteWithReasonAndParams(...concatOpts(
[ proposal.id, vote.support, vote.reason || '', vote.params ],
opts,
))
: vote.reason
// otherwise if reason
? this.governor.castVoteWithReason(...concatOpts(
[ proposal.id, vote.support, vote.reason ],
opts,
))
: this.governor.castVote(...concatOpts(
[ proposal.id, vote.support ],
opts,
));
}
waitForSnapshot (offset = 0) {
const proposal = this.currentProposal;
return this.governor.proposalSnapshot(proposal.id)
.then(blockNumber => time.advanceBlockTo(blockNumber.addn(offset)));
}
waitForDeadline (offset = 0) {
const proposal = this.currentProposal;
return this.governor.proposalDeadline(proposal.id)
.then(blockNumber => time.advanceBlockTo(blockNumber.addn(offset)));
}
waitForEta (offset = 0) {
const proposal = this.currentProposal;
return this.governor.proposalEta(proposal.id)
.then(timestamp => time.increaseTo(timestamp.addn(offset)));
}
/**
* Specify a proposal either as
* 1) an array of objects [{ target, value, data, signature? }]
* 2) an object of arrays { targets: [], values: [], data: [], signatures?: [] }
*/
setProposal (actions, description) {
let targets, values, signatures, data, useCompatibilityInterface;
if (Array.isArray(actions)) {
useCompatibilityInterface = actions.some(a => 'signature' in a);
targets = actions.map(a => a.target);
values = actions.map(a => a.value || '0');
signatures = actions.map(a => a.signature || '');
data = actions.map(a => a.data || '0x');
} else {
useCompatibilityInterface = Array.isArray(actions.signatures);
({ targets, values, signatures = [], data } = actions);
}
const fulldata = zip(signatures.map(s => s && web3.eth.abi.encodeFunctionSignature(s)), data)
.map(hexs => concatHex(...hexs));
const descriptionHash = web3.utils.keccak256(description);
// condensed version for queueing end executing
const shortProposal = [
targets,
values,
fulldata,
descriptionHash,
];
// full version for proposing
const fullProposal = [
targets,
values,
...(useCompatibilityInterface ? [ signatures ] : []),
data,
description,
];
// proposal id
const id = web3.utils.toBN(web3.utils.keccak256(web3.eth.abi.encodeParameters(
[ 'address[]', 'uint256[]', 'bytes[]', 'bytes32' ],
shortProposal,
)));
this.currentProposal = {
id,
targets,
values,
signatures,
data,
fulldata,
description,
descriptionHash,
shortProposal,
fullProposal,
useCompatibilityInterface,
};
return this.currentProposal;
}
}
module.exports = {
GovernorHelper,
};