remix-project mirror
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
remix-project/libs/remix-lib/src/execution/txHelper.ts

170 lines
5.3 KiB

'use strict'
4 years ago
import { ethers } from 'ethers'
export function makeFullTypeDefinition (typeDef) {
if (typeDef && typeDef.type.indexOf('tuple') === 0 && typeDef.components) {
const innerTypes = typeDef.components.map((innerType) => { return makeFullTypeDefinition(innerType) })
return `tuple(${innerTypes.join(',')})${extractSize(typeDef.type)}`
}
return typeDef.type
}
export function encodeParams (funABI, args) {
const types = []
if (funABI.inputs && funABI.inputs.length) {
for (let i = 0; i < funABI.inputs.length; i++) {
const type = funABI.inputs[i].type
// "false" will be converting to `false` and "true" will be working
// fine as abiCoder assume anything in quotes as `true`
if (type === 'bool' && args[i] === 'false') {
args[i] = false
}
types.push(type.indexOf('tuple') === 0 ? makeFullTypeDefinition(funABI.inputs[i]) : type)
if (args.length < types.length) {
args.push('')
}
}
}
// NOTE: the caller will concatenate the bytecode and this
// it could be done here too for consistency
const abiCoder = new ethers.utils.AbiCoder()
return abiCoder.encode(types, args)
}
export function encodeFunctionId (funABI) {
if (funABI.type === 'fallback' || funABI.type === 'receive') return '0x'
4 years ago
const abi = new ethers.utils.Interface([funABI])
return abi.getSighash(funABI.name)
}
7 years ago
4 years ago
export function getFunctionFragment (funABI): ethers.utils.Interface {
if (funABI.type === 'fallback' || funABI.type === 'receive') return null
4 years ago
return new ethers.utils.Interface([funABI])
4 years ago
}
export function sortAbiFunction (contractabi) {
// Check if function is constant (introduced with Solidity 0.6.0)
4 years ago
const isConstant = ({ stateMutability }) => stateMutability === 'view' || stateMutability === 'pure'
// Sorts the list of ABI entries. Constant functions will appear first,
// followed by non-constant functions. Within those t wo groupings, functions
// will be sorted by their names.
return contractabi.sort(function (a, b) {
if (isConstant(a) && !isConstant(b)) {
return 1
} else if (isConstant(b) && !isConstant(a)) {
return -1
}
// If we reach here, either a and b are both constant or both not; sort by name then
// special case for fallback, receive and constructor function
if (a.type === 'function' && typeof a.name !== 'undefined') {
return a.name.localeCompare(b.name)
} else if (a.type === 'constructor' || a.type === 'fallback' || a.type === 'receive') {
return 1
}
})
}
export function getConstructorInterface (abi) {
4 years ago
const funABI = { name: '', inputs: [], type: 'constructor', payable: false, outputs: [] }
if (typeof abi === 'string') {
try {
abi = JSON.parse(abi)
} catch (e) {
console.log('exception retrieving ctor abi ' + abi)
return funABI
}
}
for (let i = 0; i < abi.length; i++) {
if (abi[i].type === 'constructor') {
funABI.inputs = abi[i].inputs || []
funABI.payable = abi[i].payable
funABI['stateMutability'] = abi[i].stateMutability
break
5 years ago
}
}
return funABI
}
export function serializeInputs (fnAbi) {
let serialized = '('
if (fnAbi.inputs && fnAbi.inputs.length) {
serialized += fnAbi.inputs.map((input) => { return input.type }).join(',')
}
serialized += ')'
return serialized
}
export function extractSize (type) {
const size = type.match(/([a-zA-Z0-9])(\[.*\])/)
return size ? size[2] : ''
}
export function getFunction (abi, fnName) {
for (let i = 0; i < abi.length; i++) {
const fn = abi[i]
if (fn.type === 'function' && fnName === fn.name + '(' + fn.inputs.map((value) => {
if (value.components) {
const fullType = makeFullTypeDefinition(value)
return fullType.replace(/tuple/g, '') // return of makeFullTypeDefinition might contain `tuple`, need to remove it cause `methodIdentifier` (fnName) does not include `tuple` keyword
} else {
return value.type
}
}).join(',') + ')') {
return fn
}
}
4 years ago
return null
4 years ago
}
export function getFallbackInterface (abi) {
for (let i = 0; i < abi.length; i++) {
if (abi[i].type === 'fallback') {
return abi[i]
}
}
}
export function getReceiveInterface (abi) {
for (let i = 0; i < abi.length; i++) {
if (abi[i].type === 'receive') {
return abi[i]
}
}
}
/**
* return the contract obj of the given @arg name. Uses last compilation result.
* return null if not found
* @param {String} name - contract name
* @returns contract obj and associated file: { contract, file } or null
*/
4 years ago
export function getContract (contractName, contracts) {
for (const file in contracts) {
if (contracts[file][contractName]) {
return { object: contracts[file][contractName], file: file }
}
}
return null
}
/**
* call the given @arg cb (function) for all the contracts. Uses last compilation result
* stop visiting when cb return true
* @param {Function} cb - callback
*/
4 years ago
export function visitContracts (contracts, cb) {
for (const file in contracts) {
for (const name in contracts[file]) {
if (cb({ name: name, object: contracts[file][name], file: file })) return
}
}
}
export function inputParametersDeclarationToString (abiinputs) {
const inputs = (abiinputs || []).map((inp) => inp.type + ' ' + inp.name)
return inputs.join(', ')
}