Allow proxy mater copy pattern
This commit is contained in:
parent
deb1b8692c
commit
7a2c0b5c38
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Current Master
|
||||
|
||||
- [#436](https://github.com/poanetwork/nifty-wallet/pull/436) - Allow master copy pattern in importing of proxy contract
|
||||
- [#435](https://github.com/poanetwork/nifty-wallet/pull/435) - Allow array input type in contracts interactions
|
||||
- [#434](https://github.com/poanetwork/nifty-wallet/pull/434) - Add support of tuple type at interaction with read-only contract methods
|
||||
- [#432](https://github.com/poanetwork/nifty-wallet/pull/432) - bump rsk-contract-metadata dependency
|
||||
|
|
|
@ -25,6 +25,8 @@ class ContractImportView extends Component {
|
|||
static propTypes = {
|
||||
error: PropTypes.string,
|
||||
network: PropTypes.string,
|
||||
RPC_URL: PropTypes.string,
|
||||
provider: PropTypes.object,
|
||||
type: PropTypes.string,
|
||||
displayWarning: PropTypes.func,
|
||||
importNewAccount: PropTypes.func,
|
||||
|
@ -118,12 +120,12 @@ class ContractImportView extends Component {
|
|||
|
||||
autodetectContractABI = () => {
|
||||
const { contractAddr, web3 } = this.state
|
||||
const { type, network } = this.props
|
||||
const { type, network, provider, RPC_URL } = this.props
|
||||
if (!contractAddr || !web3.isAddress(contractAddr)) {
|
||||
this.clearABI()
|
||||
return
|
||||
}
|
||||
getFullABI(web3.eth, contractAddr, network, type)
|
||||
getFullABI(web3.eth, contractAddr, network, type, RPC_URL, provider)
|
||||
.then(finalABI => {
|
||||
if (finalABI) {
|
||||
finalABI = JSON.stringify(finalABI)
|
||||
|
@ -218,6 +220,8 @@ function mapStateToProps (state) {
|
|||
const result = {
|
||||
error: warning && (warning || warning.message),
|
||||
network: state.metamask.network,
|
||||
provider: state.metamask.provider,
|
||||
RPC_URL: state.appState.RPC_URL,
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import log from 'loglevel'
|
||||
import { importTypes } from './enums'
|
||||
import Web3 from 'web3'
|
||||
import ethNetProps from 'eth-net-props'
|
||||
import abi from 'web3-eth-abi'
|
||||
|
||||
const nestedJsonObjToArray = (jsonObj) => {
|
||||
return jsonObjToArray(jsonObj)
|
||||
|
@ -100,44 +103,88 @@ const fetchABI = (addr, network) => {
|
|||
})
|
||||
}
|
||||
|
||||
const getFullABI = (eth, contractAddr, network, type) => {
|
||||
const getFullABI = (eth, contractAddr, network, type, RPC_URL, provider) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetchABI(contractAddr, network)
|
||||
.then((targetABI) => {
|
||||
targetABI = targetABI && JSON.parse(targetABI)
|
||||
let finalABI = targetABI
|
||||
if (type === importTypes.CONTRACT.PROXY) {
|
||||
if (!eth.contract(targetABI).at(contractAddr).implementation) {
|
||||
if (!eth.contract(targetABI).at(contractAddr).implementation && !isMasterCopyPattern(targetABI)) {
|
||||
const e = {
|
||||
message: 'This is not a valid Delegate Proxy contract',
|
||||
}
|
||||
reject(e)
|
||||
}
|
||||
try {
|
||||
eth.contract(targetABI).at(contractAddr).implementation.call((err, implAddr) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
fetchABI(implAddr, network)
|
||||
.then((implABI) => {
|
||||
implABI = implABI && JSON.parse(implABI)
|
||||
finalABI = implABI ? targetABI.concat(implABI) : targetABI
|
||||
resolve(finalABI)
|
||||
})
|
||||
.catch(e => reject(e))
|
||||
if (isMasterCopyPattern(targetABI)) {
|
||||
let rpcUrl = RPC_URL || provider.rpcTarget
|
||||
if (rpcUrl === '') {
|
||||
rpcUrl = ethNetProps.RPCEndpoints(network)[0]
|
||||
}
|
||||
})
|
||||
getImplAddrFromMasterCopyPattern(contractAddr, rpcUrl)
|
||||
.then(implAddr => {
|
||||
fetchImplementationAndCombine(implAddr, targetABI, network, resolve, reject)
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
} else {
|
||||
eth.contract(targetABI).at(contractAddr).implementation.call((err, implAddr) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
fetchImplementationAndCombine(implAddr, targetABI, network, resolve, reject)
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
} else {
|
||||
resolve(finalABI)
|
||||
resolve(targetABI)
|
||||
}
|
||||
})
|
||||
.catch(e => { reject(e) })
|
||||
})
|
||||
}
|
||||
|
||||
const isMasterCopyPattern = (abi) => {
|
||||
return abi.some(method => {
|
||||
return isMasterCopyInput(method.inputs)
|
||||
})
|
||||
}
|
||||
|
||||
const isMasterCopyInput = (inputs) => {
|
||||
return inputs && inputs.find(input => {
|
||||
return input.name === '_masterCopy'
|
||||
})
|
||||
}
|
||||
|
||||
const getImplAddrFromMasterCopyPattern = (address, rpcUrl) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
|
||||
web3.eth.getStorageAt(address, 0, 'latest', (err, result) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
if (result) {
|
||||
const implAddr = abi.decodeParameter('address', result)
|
||||
resolve(implAddr)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const fetchImplementationAndCombine = (implAddr, proxyABI, network, resolve, reject) => {
|
||||
return fetchABI(implAddr, network)
|
||||
.then((implABI) => {
|
||||
implABI = implABI && JSON.parse(implABI)
|
||||
const finalABI = implABI ? proxyABI.concat(implABI) : proxyABI
|
||||
resolve(finalABI)
|
||||
})
|
||||
.catch(e => reject(e))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
nestedJsonObjToArray,
|
||||
getFullABI,
|
||||
|
|
|
@ -43,6 +43,8 @@ class AccountDropdowns extends Component {
|
|||
style: PropTypes.object,
|
||||
enableAccountOptions: PropTypes.bool,
|
||||
enableAccountsSelector: PropTypes.bool,
|
||||
RPC_URL: PropTypes.string,
|
||||
provider: PropTypes.object,
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
|
@ -229,9 +231,9 @@ class AccountDropdowns extends Component {
|
|||
}
|
||||
|
||||
updateABI = async () => {
|
||||
const { actions, selected, network } = this.props
|
||||
const { actions, selected, network, RPC_URL, provider } = this.props
|
||||
actions.showLoadingIndication()
|
||||
getFullABI(this.web3.eth, selected, network, importTypes.CONTRACT.PROXY)
|
||||
getFullABI(this.web3.eth, selected, network, importTypes.CONTRACT.PROXY, RPC_URL, provider)
|
||||
.then(finalABI => {
|
||||
actions.updateABI(selected, network, finalABI)
|
||||
.then()
|
||||
|
@ -331,6 +333,15 @@ class AccountDropdowns extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const result = {
|
||||
provider: state.metamask.provider,
|
||||
RPC_URL: state.appState.RPC_URL,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
actions: {
|
||||
|
@ -349,5 +360,5 @@ const mapDispatchToProps = (dispatch) => {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
AccountDropdowns: connect(null, mapDispatchToProps)(AccountDropdowns),
|
||||
AccountDropdowns: connect(mapStateToProps, mapDispatchToProps)(AccountDropdowns),
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ class SendTransactionScreen extends PersistentForm {
|
|||
copyDisabled: true,
|
||||
}
|
||||
|
||||
let rpcUrl = props.RPC_URL ? props.RPC_URL : props.provider.rpcTarget
|
||||
let rpcUrl = props.RPC_URL || props.provider.rpcTarget
|
||||
if (rpcUrl === '') {
|
||||
rpcUrl = ethNetProps.RPCEndpoints(props.network)[0]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue