Skip to content

Commit

Permalink
lint fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivshti committed Mar 6, 2022
1 parent 632f4d4 commit 3d5e32e
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 94 deletions.
84 changes: 55 additions & 29 deletions js/Bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ Bundle.prototype.getNonce = async function(provider) {
Bundle.prototype.estimate = async function({ fetch, relayerURL, replacing, getNextNonce }) {
const res = await fetchPost(
fetch,
`${relayerURL}/identity/${this.identity}/${this.network}/estimate${getNextNonce ? '?getNextNonce=true' : ''}`,
`${relayerURL}/identity/${this.identity}/${this.network}/estimate${
getNextNonce ? '?getNextNonce=true' : ''
}`,
{ txns: this.txns, signer: this.signer, replacing, minFeeInUSDPerGas: this.minFeeInUSDPerGas }
)
this.gasLimit = res.gasLimit
Expand All @@ -51,7 +53,14 @@ Bundle.prototype.submit = async function({ fetch, relayerURL }) {
const res = await fetchPost(
fetch,
`${relayerURL}/identity/${this.identity}/${this.network}/submit`,
{ nonce: this.nonce, signer: this.signer, txns: this.txns, gasLimit: this.gasLimit, signature: this.signature, signatureTwo: this.signatureTwo }
{
nonce: this.nonce,
signer: this.signer,
txns: this.txns,
gasLimit: this.gasLimit,
signature: this.signature,
signatureTwo: this.signatureTwo
}
)
return res
}
Expand All @@ -77,26 +86,27 @@ Bundle.prototype.estimateNoRelayer = async function({ provider, replacing }) {
if (error && error.message.startsWith('execution reverted: ')) {
const message = error.message.slice(20)
return { success: false, message }
} else if (error) {
}
if (error) {
// Match both the code and the regex to handle both errs from ethers and raw ones from nodes in case we use .send
if (!(error.code === 'UNPREDICTABLE_GAS_LIMIT' || error.message.match(UNPREDICTABLE_GAS_REGEX))) throw error
if (!(error.code === 'UNPREDICTABLE_GAS_LIMIT' || error.message.match(UNPREDICTABLE_GAS_REGEX)))
throw error
return { success: false, message: await getErrMsg(provider, txParams, blockTag) }
} else {
this.gasLimit = gasLimit.toNumber()
// @TODO EIP1559-optimized estimations (good first issue for external contributors)
const feeData = await provider.getFeeData()
const gasPrice = feeData.gasPrice.toNumber()
const baseFee = gasPrice * gasLimit / 1e18
return {
success: true,
gasLimit: this.gasLimit,
gasPrice,
feeInNative: {
slow: baseFee * 0.9,
medium: baseFee * 1.0,
fast: baseFee * 1.15,
ape: baseFee * 1.4
}
}
this.gasLimit = gasLimit.toNumber()
// @TODO EIP1559-optimized estimations (good first issue for external contributors)
const feeData = await provider.getFeeData()
const gasPrice = feeData.gasPrice.toNumber()
const baseFee = (gasPrice * gasLimit) / 1e18
return {
success: true,
gasLimit: this.gasLimit,
gasPrice,
feeInNative: {
slow: baseFee * 0.9,
medium: baseFee * 1.0,
fast: baseFee * 1.15,
ape: baseFee * 1.4
}
}
}
Expand Down Expand Up @@ -128,7 +138,12 @@ function getSignable(userTxnBundle, isSingleSigMode) {
if (signer.address)
return abiCoder.encode(
['address', 'uint', 'uint', 'tuple(address, uint, bytes)[]'],
[userTxnBundle.identity, getChainID(userTxnBundle.network), userTxnBundle.nonce, userTxnBundle.txns]
[
userTxnBundle.identity,
getChainID(userTxnBundle.network),
userTxnBundle.nonce,
userTxnBundle.txns
]
)
if (signer.quickAccManager) {
const accHash = keccak256(
Expand All @@ -141,7 +156,15 @@ function getSignable(userTxnBundle, isSingleSigMode) {
// if (signer.isTypedData)
return abiCoder.encode(
['address', 'uint', 'address', 'bytes32', 'uint', 'tuple(address, uint, bytes)[]', 'bool'],
[signer.quickAccManager, getChainID(userTxnBundle.network), userTxnBundle.identity, accHash, userTxnBundle.nonce, userTxnBundle.txns, !isSingleSigMode]
[
signer.quickAccManager,
getChainID(userTxnBundle.network),
userTxnBundle.identity,
accHash,
userTxnBundle.nonce,
userTxnBundle.txns,
!isSingleSigMode
]
)
}
throw new Error(`invalid signer object`)
Expand Down Expand Up @@ -203,12 +226,12 @@ async function fetchPost(fetch, url, body) {
// Signature of Error(string)
const ERROR_SIG = '0x08c379a0'

async function getErrMsg (provider, txParams, blockTag) {
async function getErrMsg(provider, txParams, blockTag) {
// .call always returns a hex string with ethers
try {
const returnData = await provider.call(txParams, blockTag)
return returnData.startsWith(ERROR_SIG)
? (new AbiCoder()).decode(['string'], '0x' + returnData.slice(10))[0]
? new AbiCoder().decode(['string'], `0x${returnData.slice(10)}`)[0]
: returnData
} catch (e) {
// weird infura case
Expand All @@ -219,11 +242,14 @@ async function getErrMsg (provider, txParams, blockTag) {
}
}

async function estimateGasWithCatch (provider, blockTag, tx) {
return provider.send('eth_estimateGas', [tx, blockTag])
.then(gasLimit => ({ gasLimit: BigNumber.from(gasLimit) }))
// with .send, the error is wrapped in another error
.catch(e => e.code === 'SERVER_ERROR' ? { error: e.error } : { error: e })
async function estimateGasWithCatch(provider, blockTag, tx) {
return (
provider
.send('eth_estimateGas', [tx, blockTag])
.then(gasLimit => ({ gasLimit: BigNumber.from(gasLimit) }))
// with .send, the error is wrapped in another error
.catch(e => (e.code === 'SERVER_ERROR' ? { error: e.error } : { error: e }))
)
}

// getNonce(require('ethers').getDefaultProvider('homestead'), { identity: '0x23c2c34f38ce66ccc10e71e9bb2a06532d52c5e8', signer: {address: '0x942f9CE5D9a33a82F88D233AEb3292E680230348'}, txns: [] }).then(console.log)
Expand Down
19 changes: 8 additions & 11 deletions js/IdentityProxyDeploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ function sstoreCode(slotNumber, keyType, key, valueType, valueBuf) {
function getProxyDeployBytecode(masterContractAddr, privLevels, opts = { privSlot: 0 }) {
const { privSlot = 0 } = opts
if (privLevels.length > 3) throw new Error('getProxyDeployBytecode: max 3 privLevels')
const storage = Buffer.concat(privLevels
.map(([addr, data]) => {
return data !== true ?
sstoreCode(privSlot, 'address', addr, 'bytes32', data)
const storage = Buffer.concat(
privLevels.map(([addr, data]) => {
return data !== true
? sstoreCode(privSlot, 'address', addr, 'bytes32', data)
: sstoreCode(privSlot, 'address', addr, 'bool', Buffer.from('01', 'hex'))
})
)
Expand All @@ -36,14 +36,12 @@ function getProxyDeployBytecode(masterContractAddr, privLevels, opts = { privSlo
// @TODO solve this case; this will remove the "max 3 privLevels" restriction
const offset = storage.length + initial.length + 6 // 6 more bytes including the push added later on
if (offset > 256) throw new Error('getProxyDeployBytecode: internal: offset>256')
const initialCode = Buffer.concat([
storage,
initial,
evmPush(Buffer.from([offset]))
])
const initialCode = Buffer.concat([storage, initial, evmPush(Buffer.from([offset]))])
const masterAddrBuf = Buffer.from(masterContractAddr.slice(2).replace(/^(00)+/, ''), 'hex')
if (masterAddrBuf > 20) throw new Error('invalid address')
return `0x${initialCode.toString('hex')}3d3981f3363d3d373d3d3d363d${evmPush(masterAddrBuf).toString('hex')}5af43d82803e903d91602b57fd5bf3`
return `0x${initialCode.toString('hex')}3d3981f3363d3d373d3d3d363d${evmPush(
masterAddrBuf
).toString('hex')}5af43d82803e903d91602b57fd5bf3`
}

function getStorageSlotsFromArtifact(IdentityArtifact) {
Expand All @@ -62,4 +60,3 @@ function getStorageSlotsFromArtifact(IdentityArtifact) {
}

module.exports = { evmPush, sstoreCode, getProxyDeployBytecode, getStorageSlotsFromArtifact }

3 changes: 2 additions & 1 deletion test/TestADXToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,6 @@ contract('ADXToken', function(accounts) {

// Governance can step down
await adxSupplyController.setGovernance(governance, 0)
await expectEVMError(adxSupplyController.mint(tokenAddr, userAddr, largeAmnt), 'NOT_GOVERNANCE')})
await expectEVMError(adxSupplyController.mint(tokenAddr, userAddr, largeAmnt), 'NOT_GOVERNANCE')
})
})
94 changes: 54 additions & 40 deletions test/TestIdentity.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
const promisify = require('util').promisify
const { providers, Contract } = require('ethers')
const { Interface, randomBytes, getAddress, AbiCoder, keccak256, arrayify, hexlify } = require('ethers').utils
const {
Interface,
randomBytes,
getAddress,
AbiCoder,
keccak256,
arrayify,
hexlify
} = require('ethers').utils
const { generateAddress2 } = require('ethereumjs-util')

const Outpace = artifacts.require('OUTPACE')
Expand Down Expand Up @@ -53,7 +61,7 @@ contract('Identity', function(accounts) {
const anotherAccount = accounts[7]

before(async function() {
//chainId = (await web3Provider.getNetwork()).chainId
// chainId = (await web3Provider.getNetwork()).chainId
// we seem to be using 1 in testing conditions for whatever reason
chainId = 1

Expand All @@ -71,16 +79,17 @@ contract('Identity', function(accounts) {
const idWeb3 = await Identity.new([])
baseIdentityAddr = idWeb3.address

// a hardcoded test
assert.equal(getProxyDeployBytecode('0x02a63ec1bced5545296a5193e652e25ec0bae410', [['0xe5a4Dad2Ea987215460379Ab285DF87136E83BEA', true]]), '0x60017f02c94ba85f2ea274a3869293a0a9bf447d073c83c617963b0be7c862ec2ee44e553d602d80602e3d3981f3363d3d373d3d3d363d7302a63ec1bced5545296a5193e652e25ec0bae4105af43d82803e903d91602b57fd5bf3')

const bytecode = getProxyDeployBytecode(
baseIdentityAddr,
[[userAcc, true]],
{
...getStorageSlotsFromArtifact(Identity)
}
// a hardcoded test
assert.equal(
getProxyDeployBytecode('0x02a63ec1bced5545296a5193e652e25ec0bae410', [
['0xe5a4Dad2Ea987215460379Ab285DF87136E83BEA', true]
]),
'0x60017f02c94ba85f2ea274a3869293a0a9bf447d073c83c617963b0be7c862ec2ee44e553d602d80602e3d3981f3363d3d373d3d3d363d7302a63ec1bced5545296a5193e652e25ec0bae4105af43d82803e903d91602b57fd5bf3'
)

const bytecode = getProxyDeployBytecode(baseIdentityAddr, [[userAcc, true]], {
...getStorageSlotsFromArtifact(Identity)
})
const receipt = await (await identityFactory.deploy(bytecode, 0, { gasLimit })).wait()
const deployedEv = receipt.events.find(x => x.event === 'LogDeployed')
id = new Contract(deployedEv.args.addr, Identity._json.abi, signer)
Expand All @@ -93,7 +102,10 @@ contract('Identity', function(accounts) {
})

it('protected methods', async function() {
await expectEVMError(id.setAddrPrivilege(userAcc, TRUE_BYTES, { gasLimit }), 'ONLY_IDENTITY_CAN_CALL')
await expectEVMError(
id.setAddrPrivilege(userAcc, TRUE_BYTES, { gasLimit }),
'ONLY_IDENTITY_CAN_CALL'
)
})

it('deploy an Identity, counterfactually', async function() {
Expand Down Expand Up @@ -143,11 +155,8 @@ contract('Identity', function(accounts) {
const hash = hashTxns(id.address, 1, initialNonce, [relayerTx])

// Non-authorized address does not work
const invalidSig = await signMsg(evilAcc, hash)
await expectEVMError(
id.execute([relayerTx], invalidSig),
'INSUFFICIENT_PRIVILEGE'
)
const invalidSig = await signMsg(evilAcc, hash)
await expectEVMError(id.execute([relayerTx], invalidSig), 'INSUFFICIENT_PRIVILEGE')

// Do the execute() correctly, verify if it worked
const relayerTxSig = await signMsg(userAcc, hash)
Expand All @@ -172,10 +181,7 @@ contract('Identity', function(accounts) {
idInterface.encodeFunctionData('setAddrPrivilege', [userAcc, FALSE_BYTES])
]
const sig = await signMsg(userAcc, hashTxns(id.address, chainId, 1, [relayerDowngradeTx]))
await expectEVMError(
id.execute([relayerDowngradeTx], sig),
'PRIVILEGE_NOT_DOWNGRADED'
)
await expectEVMError(id.execute([relayerDowngradeTx], sig), 'PRIVILEGE_NOT_DOWNGRADED')
})

it('quickAccount signature validation', async function() {
Expand All @@ -195,13 +201,17 @@ contract('Identity', function(accounts) {
])

// The part that is evaluated by QuickAccManager
const sigInner = abiCoder.encode([ 'uint', 'bytes', 'bytes' ], [600, sig1, sig2])
const sig = sigInner + abiCoder.encode(['address'], [quickAccManager.address]).slice(2) + '02'
const sigInner = abiCoder.encode(['uint', 'bytes', 'bytes'], [600, sig1, sig2])
const sig = `${sigInner + abiCoder.encode(['address'], [quickAccManager.address]).slice(2)}02`

// we need to deploy before being able to validate sigs
const deployReceipt = await (await deploy()).wait()
const deployedEv = deployReceipt.events.find(x => x.event === 'LogDeployed')
const identity = new Contract(deployedEv.args.addr, Identity._json.abi, web3Provider.getSigner(userAcc))
const identity = new Contract(
deployedEv.args.addr,
Identity._json.abi,
web3Provider.getSigner(userAcc)
)
// 0x1626ba7e is the signature that the function has to return in case of successful verification
assert.equal(await identity.isValidSignature(msgHash, sig), '0x1626ba7e')
})
Expand All @@ -212,10 +222,16 @@ contract('Identity', function(accounts) {
// First, prepare to authorize the quickAccount
const quickAccount = [600, userAcc, anotherAccount]
const accHash = keccak256(abiCoder.encode(['tuple(uint, address, address)'], [quickAccount]))
const authorizeQuickAcc = () =>
(new Contract(id.address, Identity._json.abi, web3Provider.getSigner(userAcc))).executeBySender([
[ id.address, 0, idInterface.encodeFunctionData('setAddrPrivilege', [quickAccManager.address, accHash]) ]
])
const authorizeQuickAcc = () =>
new Contract(id.address, Identity._json.abi, web3Provider.getSigner(userAcc)).executeBySender(
[
[
id.address,
0,
idInterface.encodeFunctionData('setAddrPrivilege', [quickAccManager.address, accHash])
]
]
)

// Try relaying a txn
const relayerTx = [
Expand All @@ -231,15 +247,13 @@ contract('Identity', function(accounts) {
])

// The part that is evaluated by QuickAccManager
const sigInner = abiCoder.encode([ 'uint', 'bytes', 'bytes' ], [600, sig1, sig2])
const sigInner = abiCoder.encode(['uint', 'bytes', 'bytes'], [600, sig1, sig2])
// smart contract sig for quickAccManager.address
const dualSig = sigInner + abiCoder.encode(['address'], [quickAccManager.address]).slice(2) + '02'
const dualSig = `${sigInner +
abiCoder.encode(['address'], [quickAccManager.address]).slice(2)}02`

// Not authorized yet
await expectEVMError(
id.execute([relayerTx], dualSig, { gasLimit }),
'SV_WALLET_INVALID'
)
await expectEVMError(id.execute([relayerTx], dualSig, { gasLimit }), 'SV_WALLET_INVALID')

// Authorize the QuickAccManager with this accHash
await authorizeQuickAcc()
Expand Down Expand Up @@ -320,10 +334,7 @@ contract('Identity', function(accounts) {
idInterface.encodeFunctionData('setAddrPrivilege', [userAcc, TRUE_BYTES])
]

await expectEVMError(
id.executeBySender([relayerTx]),
'INSUFFICIENT_PRIVILEGE'
)
await expectEVMError(id.executeBySender([relayerTx]), 'INSUFFICIENT_PRIVILEGE')

const idWithUser = new Contract(id.address, Identity._json.abi, web3Provider.getSigner(userAcc))
const receipt = await (await idWithUser.executeBySender([relayerTx], {
Expand Down Expand Up @@ -615,7 +626,10 @@ contract('Identity', function(accounts) {
*/
function hashTxns(identityAddr, chainId, nonce, txns) {
const abiCoder = new AbiCoder()
const encoded = abiCoder.encode(['address', 'uint', 'uint', 'tuple(address, uint, bytes)[]'], [identityAddr, chainId, nonce, txns])
const encoded = abiCoder.encode(
['address', 'uint', 'uint', 'tuple(address, uint, bytes)[]'],
[identityAddr, chainId, nonce, txns]
)
return arrayify(keccak256(encoded))
}

Expand All @@ -629,7 +643,7 @@ contract('Identity', function(accounts) {
async function signMsg(from, hash) {
assert.equal(hash.length, 32, 'hash must be 32byte array buffer')
// 01 is the enum number of EthSign signature type
return mapSignatureV(await web3Provider.getSigner(from).signMessage(hash)) + '01'
return `${mapSignatureV(await web3Provider.getSigner(from).signMessage(hash))}01`
}

function createAccount(privileges, opts) {
Expand Down
4 changes: 3 additions & 1 deletion test/TestStakingPool.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,9 @@ contract('StakingPool', function(accounts) {

await expectEVMError(stakingPool.leave(parseADX('10000'), false), 'INSUFFICIENT_SHARES')

const receipt = await (await stakingPool.leave(sharesToMint, false, { gasLimit: 150000 })).wait()
const receipt = await (await stakingPool.leave(sharesToMint, false, {
gasLimit: 150000
})).wait()
const currentBlockTimestamp = (await web3.eth.getBlock('latest')).timestamp
assert.equal(receipt.events.length, 2, 'should emit LogLeave event')

Expand Down
Loading

0 comments on commit 3d5e32e

Please sign in to comment.