Published
Edited
Oct 13, 2020
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {
Env,
World,
defaultEnv,
ganacheEnv,
etherscan,
github,
areEqual,
assert,
exp,
num,
EVMLib
} from "@jflatow/quest"
Insert cell
Insert cell
etherscanExample = {
const env = await (new Env).read(github())
const abi = await etherscan.getABI(env.address('Comptroller'))
const src = await etherscan.getSource(env.address('cBAT'))
const clone = await (new Env).loads(env.dumps())
await assert(areEqual(env.dumps(), clone.dumps()))
return {env, abi, src, clone}
}
Insert cell
Insert cell
Insert cell
{
const result1 = await (new World).eval(a => a + 1, {expect: 2}, 1)
const result2 = await (new World).eval(a => a + 1, {expect: v => v == 2}, 1)
const world = await (new World).exec([{eval: a => a + 1, expect: 2}], 1)
await assert(result1 == result2)
return {result1, result2, world}
}
Insert cell
Insert cell
(new World).eval(a => a + 1, {expect: 3}, 1)
Insert cell
(new World).eval(a => a + 1, {expect: _ => false}, 1)
Insert cell
Insert cell
Insert cell
forkExample = {
const network = 'mainnet'
const env = await ganacheEnv.read(github(`networks/${network}.json`))
const world = new World(env), {address, bool, uint} = env.bindings()
const evmLib = await env.library(EVMLib)
const forkInfo = await world.fork(network, {unlocked_accounts: [address('Timelock')]})

const firstBal = await num.wei(world.web3.eth.getBalance(address('$0')))
const coinbaseInt = await num.hex(world.rpc('eth_coinbase'))
const lastBlock = await world.rpc('eth_getBlockByNumber', {params: ['latest', true]})
const nopCall = await world.call('notAMethod', {on: address(0xabc), args: [3, 'ok', address(0)]})
const badSend = await world.send('_setBorrowPaused', {
to: address('Comptroller'),
args: [address('cBAT'), true],
revert: 'only pause guardian and admin can pause'
})
const offset = await evmLib.$increaseTime(100)
const newBlock = await evmLib.$$advanceBlocks(300)
return {network, env, world, forkInfo, firstBal, coinbaseInt, lastBlock, nopCall, badSend, offset, newBlock}
}
Insert cell
Insert cell
x = {
const {env, world} = forkExample;
const {address, Proposal, Receipt, ProposalState} = await env.library(CompGovLib)
return await world.call('state', {on: address('GovernorAlpha'), args: [3], returns: ProposalState})
}
Insert cell
forkExample.env.typedefs.ProposalState.defn[x]
Insert cell
Insert cell
forkExample.world.send('_setBorrowPaused', {
to: forkExample.env.address('Comptroller'),
args: [forkExample.env.address('cBAT'), true],
from: forkExample.env.address('Timelock'),
gasPrice: 100
})
Insert cell
Insert cell
{
const {address} = forkExample.env.bindings()

return forkExample.world.exec([
{eval: () => 'ok'},
{call: '_setBorrowPaused', on: address('Comptroller'), args: ['0xbad', true], revert: ''}, // trapped it!
{call: '_setBorrowPaused', on: address('Comptroller'), args: [address(0), true]}
])
}
Insert cell
Insert cell
forkExample.world.send('_setBorrowPaused', {
to: forkExample.env.address('Comptroller'),
args: [forkExample.env.address('cBAT'), true],
from: forkExample.env.address('Timelock'),
gasPrice: 100,
revert: 'only pause guardian and admin can pause'
})
Insert cell
Insert cell
forkExample.world.send('_setBorrowPaused', {
to: forkExample.env.address('Comptroller'),
args: [forkExample.env.address(0), true],
from: forkExample.env.address('Timelock'),
gasPrice: 0,
revert: 'only pause guardian and admin can pause'
})
Insert cell
Insert cell
Insert cell
deployExample = {
const {env, world} = forkExample;
await env.load(await FileAttachment("compound_protocol.contracts.json").json(), true)
return world.deploy('SimplePriceOracle')
}
Insert cell
{
const {env, world} = deployExample && forkExample;
const {address, uint} = forkExample.env.bindings()
return forkExample.world.deploy('DAIInterestRateModelV2', {args: [0, 0, address(0), address(0)], revert: ''})
}
Insert cell
Insert cell
Insert cell
{
// Use the fork setup, but add to it a bit
const {env, world} = forkExample;
const {address} = env.bindings()

await env.assign({
// settings for deployment
reporter: address(0x456),
anchorToleranceMantissa: exp(.1),
anchorPeriod: 30 * 60,
tokenConfigs: [],
// setings for governance
votingPeriodWait: 20000,
timelockDelayWait: 604910,

// settings for sanity checks
btcUsdPrice: 9100190000,
ethUsdPrice: 226815000
}, true)
await env.load(await FileAttachment("open_oracle.contracts.json").json(), true)

// Import some libraries
const Compound = await env.library(CompoundLib)
const {
deployUniswapAnchoredView,
checkUniswapAnchoredView,
proposePriceFeed,
voteForQueueAndExecuteProposal,
lastProposal
} = await env.library(UniswapAnchoredViewLib)
// Compose one more check using our library primitives
const passLastProposal = async (world) => voteForQueueAndExecuteProposal(lastProposal(world), world)
// Now check this scenario
await world.exec([
// deploy
deployUniswapAnchoredView,
checkUniswapAnchoredView,

// ratify
proposePriceFeed,
passLastProposal,
// verify
Compound.basicInteractions
])
}
Insert cell
Insert cell
function UniswapAnchoredViewLib({abi, address, uint, array, Enum, Struct}, env) {
const {
$mineBlock,
$increaseTime,
$$advanceBlocks
} = env.library(EVMLib)

return {
PriceSource: new Enum('PriceSource', ['FIXED_ETH', 'FIXED_USD', 'REPORTER']),
TokenConfig: new Struct('TokenConfig', {
cToken: 'address',
underlying: 'address',
symbolHash: 'bytes32',
baseUnit: 'uint256',
priceSource: 'PriceSource',
fixedPrice: 'uint256',
uniswapMarket: 'address',
isUniswapReversed: 'bool'
}),

deployUniswapAnchoredView: async (world) => world.exec([
{deploy: 'OpenOraclePriceData', as: 'priceData', force: true},
{deploy: 'UniswapAnchoredView', as: 'priceFeed', force: true, args: [
() => address('priceData'), // note: need to thunk it, or else not defined yet!
address('reporter'),
uint('anchorToleranceMantissa'),
uint('anchorPeriod'),
array('TokenConfig')('tokenConfigs')
]}
]),

checkUniswapAnchoredView: async (world) => world.exec([
{call: 'price', on: address('priceFeed'), args: ['BTC'], expect: uint('btcUsdPrice')},
{call: 'price', on: address('priceFeed'), args: ['ETH'], expect: uint('ethUsdPrice')},
]),

proposePriceFeed: async (world) => world.exec([
{send: 'delegate', to: 'Comp', args: [address('CompHolder')], from: 'CompHolder'},
{send: 'propose', to: 'GovernorAlpha', args: [
[address('Comptroller')],
[0],
['_setPriceOracle(address)'],
[abi.encode(address('priceFeed'))],
"Migrate to Compound Price Feed"
], from: 'CompHolder'}
]),

voteForQueueAndExecuteProposal: async (proposalId, world) => world.exec([
$mineBlock(),
{send: 'castVote', to: 'GovernorAlpha', args: [proposalId, true], from: 'CompHolder'},
$$advanceBlocks(uint('votingPeriodWait')),
{send: 'queue', to: 'GovernorAlpha', args: [proposalId]},
$increaseTime(uint('timelockDelayWait')),
{send: 'execute', to: 'GovernorAlpha', args: [proposalId]}
]),

lastProposal: async (world) => world.call('proposalCount', {on: 'GovernorAlpha'})
}
}
Insert cell
Insert cell
Insert cell
function CompoundLib({abi, address, uint, array, Enum, Struct}) {
async function basicMintAndRedeem(world) {}
async function basicBorrowAndRepay(world) {}
async function basicLiquidate(world) {}
async function basicInteractions(world) {
await basicMintAndRedeem(world)
await basicBorrowAndRepay(world)
await basicLiquidate(world)
}
return {
basicMintAndRedeem,
basicBorrowAndRepay,
basicLiquidate,
basicInteractions
}
}
Insert cell
function CompGovLib({abi, address, uint, array, Enum, Struct}) {
return {
Proposal: new Struct('Proposal', {
id: 'uint',
proposer: 'address',
eta: 'uint',
targets: 'address[]',
values: 'uint[]',
signatures: 'string[]',
calldatas: 'bytes[]',
startBlock: 'uint',
endBlock: 'uint',
forVotes: 'uint',
againstVotes: 'uint',
canceled: 'bool',
executed: 'bool'
}),

Receipt: new Struct('Receipt', {
hasVoted: 'bool',
support: 'bool',
votes: 'uint96'
}),

ProposalState: new Enum('ProposalState', [
'Pending',
'Active',
'Canceled',
'Defeated',
'Succeeded',
'Queued',
'Expired',
'Executed'
])
}
}
Insert cell
Insert cell
Insert cell
abiTricksExample = {
const {abi, address, uint, bool} = defaultEnv.bindings()

const traditional = abi.coder.encodeFunctionCall({
name: 'myMethod',
type: 'function',
inputs: [
{type: 'uint256', name: 'myNumber'},
{type: 'string', name: 'myString'}
]
}, ['2345675643', 'Hello!%'])

const simplified = abi.encodeFunctionCall('myMethod', [2345675643, 'Hello!%'])
await assert(traditional == simplified, 'abi encoding broken!')
const envelope = abi.shape([uint(3), bool(false), address(123)])
await assert(areEqual(envelope.components.map(c => c.type), ['uint256', 'bool', 'address']))

return {traditional, simplified, envelope}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more