Skip to content

Commit

Permalink
Merge pull request #5178 from ethereum/vyper-compiler-updates
Browse files Browse the repository at this point in the history
Vyper compiler updates
  • Loading branch information
joeizang authored Sep 19, 2024
2 parents 06512f3 + fc19b90 commit e1cc29e
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 98 deletions.
109 changes: 55 additions & 54 deletions apps/remix-ide-e2e/src/tests/vyper_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = {
.frameParent()
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: "//*[@data-id='workspacesSelect' and contains(.,'snekmate')]",
selector: "//*[@data-id='workspacesSelect' and contains(.,'vyper')]",
locateStrategy: 'xpath',
timeout: 120000
})
Expand All @@ -36,37 +36,38 @@ module.exports = {
locateStrategy: 'xpath',
timeout: 120000
})
.openFile('examples')
.openFile('examples/auctions')
.openFile('examples/auctions/blind_auction.vy')
},
// 'Add vyper file to run tests #group1': function (browser: NightwatchBrowser) {
// browser.addFile('TestBallot.sol', sources[0]['TestBallot.sol'])

// '@sources': () => sources,
// 'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) {
// browser
// // .click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
// // .rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
// // .waitForElementPresent('[data-id="contextMenuItemvyper"]')
// // .click('[data-id="contextMenuItemvyper"]')
// .clickLaunchIcon('vyper')
// // @ts-ignore
// .frame(0)
// .waitForElementVisible({
// selector:'[data-id="compilation-details"]',
// timeout: 120000
// })
// .click('[data-id="compilation-details"]')
// .frameParent()
// .waitForElementVisible('[data-id="copy-abi"]')
// .waitForElementVisible({
// selector: "//*[@class='variable-value' and contains(.,'highestBidder')]",
// locateStrategy: 'xpath',
// })
// },
'@sources': () => sources,
'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) {
browser
.addFileSnekmate('blind_auction.vy', sources[0]['blindAuction'])
.click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.waitForElementPresent('[data-id="contextMenuItemvyper"]')
.click('[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
// @ts-ignore
.frame(0)
.waitForElementVisible({
selector:'[data-id="compilation-details"]',
timeout: 120000
})
.click('[data-id="compilation-details"]')
.frameParent()
.waitForElementVisible('[data-id="copy-abi"]')
.waitForElementVisible({
selector: "//*[@class='variable-value' and contains(.,'highestBidder')]",
locateStrategy: 'xpath',
})
},

'Compile blind_auction should success #group1': function (browser: NightwatchBrowser) {
browser
// @ts-ignore
.clickLaunchIcon('vyper')
.frame(0)
.click('[data-id="compile"]')
.waitForElementVisible({
Expand Down Expand Up @@ -145,32 +146,32 @@ module.exports = {
})
},

'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) {
let contractAddress
browser
.frameParent()
.clickLaunchIcon('filePanel')
.switchWorkspace('snekmate')
.openFile('src')
.openFile('src/snekmate')
.openFile('src/snekmate/auth')
.openFile('src/snekmate/auth/Ownable.vy')
.rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]')
.waitForElementVisible('*[data-id="contextMenuItemvyper"]')
.click('*[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
// @ts-ignore
.frame(0)
.click('[data-id="compile"]')
.waitForElementVisible({
selector:'[data-id="compilation-details"]',
timeout: 60000
})
.click('[data-id="compilation-details"]')
.frameParent()
.waitForElementVisible('[data-id="copy-abi"]')
.end()
}
// 'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) {
// let contractAddress
// browser
// .frameParent()
// .clickLaunchIcon('filePanel')
// .switchWorkspace('vyper')
// .openFile('src')
// .openFile('src/snekmate')
// .openFile('src/snekmate/auth')
// .openFile('src/snekmate/auth/Ownable.vy')
// .rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]')
// .waitForElementVisible('*[data-id="contextMenuItemvyper"]')
// .click('*[data-id="contextMenuItemvyper"]')
// .clickLaunchIcon('vyper')
// // @ts-ignore
// .frame(0)
// .click('[data-id="compile"]')
// .waitForElementVisible({
// selector:'[data-id="compilation-details"]',
// timeout: 60000
// })
// .click('[data-id="compilation-details"]')
// .frameParent()
// .waitForElementVisible('[data-id="copy-abi"]')
// .end()
// }
}

const testContract = `
Expand Down Expand Up @@ -209,7 +210,7 @@ const sources = [{

'blindAuction' : { content: `
# Blind Auction. Adapted to Vyper from [Solidity by Example](https://github.com/ethereum/solidity/blob/develop/docs/solidity-by-example.rst#blind-auction-1)
#pragma version ^0.3.10
#pragma version >0.3.10
struct Bid:
blindedBid: bytes32
Expand Down Expand Up @@ -384,6 +385,6 @@ def auctionEnd():
# Transfer funds to beneficiary
send(self.beneficiary, self.highestBid)
`}
` }
}
]
4 changes: 2 additions & 2 deletions apps/vyper/src/app/components/CompilerButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Fragment, useEffect, useState } from 'react'
import {isVyper, compile, toStandardOutput, isCompilationError, remixClient, normalizeContractPath, compileContract, RemixClient} from '../utils'
import { isVyper, compile, toStandardOutput, isCompilationError, remixClient, normalizeContractPath, compileContract, RemixClient } from '../utils'
import Button from 'react-bootstrap/Button'

interface Props {
Expand All @@ -11,7 +11,7 @@ interface Props {
remixClient: RemixClient
}

function CompilerButton({contract, setOutput, compilerUrl, resetCompilerState, output, remixClient}: Props) {
function CompilerButton({ contract, setOutput, compilerUrl, resetCompilerState, output, remixClient }: Props) {
const [loadingSpinner, setLoadingSpinnerState] = useState(false)

if (!contract || !contract) {
Expand Down
80 changes: 50 additions & 30 deletions apps/vyper/src/app/utils/compiler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,30 @@ export function normalizeContractPath(contractPath: string): string[] {
return [folders,resultingPath, filename]
}

function parseErrorString(errorString) {
function parseErrorString(errorStructure: string[]) {
// Split the string into lines
let lines = errorString.trim().split('\n')
// Extract the line number and message
let message = errorString.trim()
let targetLine = lines[2].split(',')
let tline = lines[2].trim().split(' ')[1].split(':')
let errorType = ''
let message = ''
let tline = ''
errorStructure.forEach(errorMsg => {
const choppedup = errorMsg.split(': ')
errorType = choppedup[0].trim().split('\n')[1]
message = choppedup[1]
// if (errorStructure.length > 2) {
// console.log(choppedup[2].split(',')[1])
// }
// console.log(choppedup)
})
let lines = errorStructure[0].trim().split('\n')

const errorObject = {
status: 'failed',
message: message,
column: tline[1],
line: tline[0]
message: `${errorType} - ${message}`,
column: '',
line: ''
}
message = null
targetLine = null
// targetLine = null
lines = null
tline = null
return errorObject
Expand Down Expand Up @@ -109,10 +117,10 @@ const compileReturnType = (output, contract) => {
const normal = normalizeContractPath(contract)[2]
const abi = temp[normal]['abi']
const evm = _.merge(temp[normal]['evm'])
const dpb = evm.deployedBytecode
const depByteCode = evm.deployedBytecode
const runtimeBytecode = evm.bytecode
const methodIdentifiers = evm.methodIdentifiers
const version = output?.compilers[0]?.version ?? '0.3.10'
const version = output?.compilers[0]?.version ?? '0.4.0'
const optimized = output?.compilers[0]?.settings?.optimize ?? true
const evmVersion = ''

Expand All @@ -129,7 +137,7 @@ const compileReturnType = (output, contract) => {
} = {
contractName: normal,
abi,
bytecode: dpb,
bytecode: depByteCode,
runtimeBytecode,
ir: '',
methodIdentifiers,
Expand All @@ -140,26 +148,32 @@ const compileReturnType = (output, contract) => {
return result
}

const fixContractContent = (content: string) => {
if (content.length === 0) return
const pragmaFound = content.includes('#pragma version ^0.3.10')
const wrongpragmaFound = content.includes('# pragma version ^0.3.10')
const evmVerFound = content.includes('#pragma evm-version shanghai')
const pragma = '#pragma version ^0.3.10'
const evmVer = '#pragma evm-version shanghai'

if (evmVerFound === false) {
content = `${evmVer}\n${content}`
}
if (wrongpragmaFound === true) {
content = content.replace('# pragma version ^0.3.10', '')
const updatePragmaDeclaration = (content: string) => {
const pragmaRegex = /#\s*pragma\s+[@]*version\s+([~<>!=^]+)\s*(\d+\.\d+\.\d+)/
const oldPragmaRegex = /#\s*pragma\s+[@]*version\s+([\^^]+)\s*(\d+\.\d+\.\d+)/
const oldPragmaDeclaration = ['# pragma version ^0.2.16', '# pragma version ^0.3.10', '#pragma version ^0.2.16', '#pragma version ^0.3.10']
const pragmaFound = content.match(pragmaRegex)
const oldPragmaFound = content.match(oldPragmaRegex)

const pragma = '# pragma version ~=0.4.0'

if (oldPragmaFound) {
// oldPragmaDeclaration.forEach(declaration => {
// content = content.replace(declaration, '# pragma version >0.3.10')
// })
return content
}
if (pragmaFound === false ) {
content = `${pragma}\n${content}`
if (!pragmaFound) {
content = `${pragma}\n\n${content}`
}
return content
}

const fixContractContent = (content: string) => {
if (content.length === 0) return
return updatePragmaDeclaration(content)
}

/**
* Compile the a contract
* @param url The url of the compiler
Expand All @@ -174,13 +188,16 @@ export async function compile(url: string, contract: Contract): Promise<any> {
throw new Error('Use extension .vy for Vyper.')
}

const cleanedUpContent = fixContractContent(contract.content)

let contractName = contract['name']
const compilePackage = {
manifest: 'ethpm/3',
sources: {
[contractName] : { content : fixContractContent(contract.content) }
[contractName] : { content : cleanedUpContent }
}
}

let response = await axios.post(`${url}compile`, compilePackage )

if (response.status === 404) {
Expand All @@ -194,6 +211,7 @@ export async function compile(url: string, contract: Contract): Promise<any> {
contractName = null
response = null
let result: any
let intermediateError

const status = await (await axios.get(url + 'status/' + compileCode , {
method: 'Get'
Expand All @@ -208,7 +226,9 @@ export async function compile(url: string, contract: Contract): Promise<any> {
const intermediate = await(await axios.get(url + 'exceptions/' + compileCode , {
method: 'Get'
})).data
result = parseErrorString(intermediate[0])
// console.log('Errors found', intermediate)
result = parseErrorString(intermediate)
intermediateError = intermediate
return result
}
await new Promise((resolve) => setTimeout(() => resolve({}), 3000))
Expand Down
24 changes: 12 additions & 12 deletions apps/vyper/src/app/utils/remix-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,23 @@ export class RemixClient extends PluginClient<any, CustomRemixApi> {

try {
// @ts-ignore
this.call('notification', 'toast', 'cloning Snekmate Vyper repository...')
this.call('notification', 'toast', 'cloning Snekmate Vyper repository...')
await this.call(
'dgitApi',
'clone',
{url: 'https://github.com/pcaversaccio/snekmate', token: null, branch: 'main', singleBranch: false, workspaceName: 'snekmate'},
{ url: 'https://github.com/vyperlang/vyper', token: null, branch: 'master', singleBranch: false, workspaceName: 'vyper' },
)

await this.call(
'dgitApi',
'checkout',
{
ref:'v0.0.5',
force: true,
refresh: true,
}
)
// await this.call(
// 'dgitApi',
// 'checkout',
// {
// ref:'v0.0.5',
// force: true,
// refresh: true,
// }
// )

this.call(
// @ts-ignore
'notification',
Expand Down

0 comments on commit e1cc29e

Please sign in to comment.