Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receive bug and more tests #2562

Merged
merged 6 commits into from
Jan 30, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions src/app/ui/universal-dapp-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address
<label class="pt-2 border-top d-flex justify-content-start flex-grow-1">
Low level interactions with contract
</label>
<a href="https://solidity.readthedocs.io/en/v0.6.2/contracts.html#receive-ether-function" class="" title="the link to documentation" target="_blank">
<a href="https://solidity.readthedocs.io/en/v0.6.2/contracts.html#receive-ether-function" title="the link to documentation" target="_blank">
<i aria-hidden="true" class="fas fa-info text-info my-2 mr-2"></i>
</a>
</div>
Expand All @@ -151,42 +151,55 @@ UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address
`

function sendData () {
let error = false
function setLLIError (text) {
llIError.innerText = text
if (text !== '') error = true
}

setLLIError('')
const fallback = self.udapp.getFallbackInterface(contractABI)
const receive = self.udapp.getReceiveInterface(contractABI)
const args = {
funABI: fallback,
funABI: fallback || receive,
address: address,
contractName: contractName,
contractABI: contractABI
}
let calldata = calldataInput.value
const amount = document.querySelector('#value').value
if (amount !== '0') {
// check for numeric and receive/fallback
if (!helper.isNumeric(amount)) {
setLLIError('Value to send should be a number')
return setLLIError('Value to send should be a number')
} else if (!receive && !(fallback && fallback.stateMutability === 'payable')) {
setLLIError("In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function")
return setLLIError("In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function")
}
}
let calldata = calldataInput.value
if (calldata) {
if (calldata.length > 3 && calldata.substr(0, 2) === '0x') {
if (!helper.isHexadecimal(calldata.substr(2, calldata.length))) {
setLLIError('the calldata should be a valid hexadecimal value.')
if (calldata.length < 2 || calldata.length < 4 && helper.is0XPrefixed(calldata)) {
return setLLIError('the calldata should be a valid hexadecimal value with size of at least one byte.')
} else {
if (helper.is0XPrefixed(calldata)) {
calldata = calldata.substr(2, calldata.length)
}
if (!helper.isHexadecimal(calldata)) {
return setLLIError('the calldata should be a valid hexadecimal value with size of at least one byte.')
}
}
if (!fallback) {
setLLIError("'fallback' function is not defined")
return setLLIError("'Fallback' function is not defined")
}
}
if ((calldata || amount !== '0') && !error) self.runTransaction(false, args, null, calldata, null)

if (!receive && !fallback) return setLLIError(`Both 'receive' and 'fallback' functions are not defined`)

// we have to put the right function ABI:
// if receive is defined and that there is no calldata => receive function is called
// if fallback is defined => fallback function is called
if (receive && !calldata) args.funABI = receive
else if (fallback) args.funABI = fallback

if (!args.funABI) return setLLIError(`Please define a 'Fallback' function to send calldata and a either 'Receive' or payable 'Fallback' to send ethers`)
self.runTransaction(false, args, null, calldataInput.value, null)
}

contractActionsWrapper.appendChild(lowLevelInteracions)
Expand Down
5 changes: 4 additions & 1 deletion src/lib/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ module.exports = {
return name.match(/[:*?"<>\\'|]/) != null
},
isHexadecimal (value) {
return /^[0-9a-fA-F]+$/.test(value)
return /^[0-9a-fA-F]+$/.test(value) && (value.length % 2 === 0)
},
is0XPrefixed (value) {
return value.substr(0, 2) === '0x'
},
isNumeric (value) {
return /^\+?(0|[1-9]\d*)$/.test(value)
Expand Down
92 changes: 75 additions & 17 deletions test-browser/tests/specialFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@
var init = require('../helpers/init')
var sauce = require('./sauce')

/**
* both are declared, sending data
* both are declared - receive called, sending wei
* both are declared - fallback should fail cause not payable, sending data and wei
* receive is declared, failing, fallback is not declared, sending data
* receive is not declared, fallback is payable, sending wei
* receive is not declared, fallback is payable, sending data and wei
* both are not declared, sending data and wei, should fail
*/
module.exports = {
before: function (browser, done) {
init(browser, done)
Expand All @@ -36,7 +27,19 @@ module.exports = {
})
})
},
'Use special functions receive/follback - both are declared - receive called, sending wei': function (browser) {
'Use special functions receive/fallback - both are declared - receive called, failing sending data < 1 byte': function (browser) {
// don't need to redeploy it, same contract
browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => {
browser.sendLowLevelTx(address, '0', '0xa')
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `the calldata should be a valid hexadecimal value with size of at least one byte.`)
.perform(done)
})
})
},
'Use special functions receive/fallback - both are declared - receive called, sending wei': function (browser) {
// don't need to redeploy it, same contract
browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => {
Expand All @@ -49,7 +52,7 @@ module.exports = {
})
})
},
'Use special functions receive/follback - both are declared - fallback should fail cause not payable, sending data and wei': function (browser) {
'Use special functions receive/fallback - both are declared - fallback should fail cause not payable, sending data and wei': function (browser) {
// don't need to redeploy it, same contract
browser.perform((done) => {
browser.getAddressAtPosition(0, (address) => {
Expand All @@ -61,24 +64,37 @@ module.exports = {
})
})
},
'Use special functions receive/follback - receive is declared, failing, fallback is not declared, sending data': function (browser) {
'Use special functions receive/fallback - only receive is declared, sending wei': function (browser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('receiveOnly.sol', sources[1]['browser/receiveOnly.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.createContract('')
.clickInstance(1)
.perform((done) => {
browser.getAddressAtPosition(1, (address) => {
browser.sendLowLevelTx(address, '1', '')
.pause(1000)
.journalLastChildIncludes('to:CheckSpecials.(receive)')
.journalLastChildIncludes('value:1 wei')
.journalLastChildIncludes('data:0x')
.perform(done)
})
})
},
'Use special functions receive/fallback - only receive is declared, failing, fallback is not declared, sending data': function (browser) {
// don't need to redeploy it, same contract
browser.perform((done) => {
browser.getAddressAtPosition(1, (address) => {
browser.sendLowLevelTx(address, '0', '0xaa')
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `'fallback' function is not defined`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `'Fallback' function is not defined`)
.perform(done)
})
})
},
'Use special functions receive/fallback - receive is not declared, fallback is payable, sending wei': function (browser) {
'Use special functions receive/fallback - only fallback is payable, sending wei': function (browser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('fallbackOnlyPayable.sol', sources[2]['browser/fallbackOnlyPayable.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
Expand All @@ -96,7 +112,7 @@ module.exports = {
})
})
},
'Use special functions receive/follback - receive is not declared, fallback is payable, sending data and wei': function (browser) {
'Use special functions receive/fallback - only fallback is diclared and is payable, sending data and wei': function (browser) {
// don't need to redeploy it, same contract
browser.perform((done) => {
browser.getAddressAtPosition(2, (address) => {
Expand All @@ -109,7 +125,7 @@ module.exports = {
})
})
},
'Use special functions receive/fallback - receive is not declared, fallback should fail cause not payable, sending wei': function (browser) {
'Use special functions receive/fallback - only fallback is declared, fallback should fail cause not payable, sending wei': function (browser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('fallbackOnlyNotPayable.sol', sources[3]['browser/fallbackOnlyNotPayable.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
Expand All @@ -136,7 +152,7 @@ module.exports = {
.setValue('#value', 0)
.createContract('')
.clickInstance(4)
.pause(10000)
.pause(1000)
.perform((done) => {
browser.getAddressAtPosition(4, (address) => {
browser.sendLowLevelTx(address, '1', '0xaa')
Expand All @@ -147,6 +163,39 @@ module.exports = {
.perform(done)
})
})
},
'Use special functions receive/fallback - receive and fallback are declared and payable, sending wei': function (browser) {
browser.perform((done) => {
browser.getAddressAtPosition(4, (address) => {
browser.sendLowLevelTx(address, '1', '')
.pause(1000)
.journalLastChildIncludes('to:CheckSpecials.(receive)')
.journalLastChildIncludes('value:1 wei')
.journalLastChildIncludes('data:0x')
.perform(done)
})
})
},
'Use special functions receive/fallback - receive and fallback are not declared, sending nothing': function (browser) {
browser.waitForElementVisible('#icon-panel', 10000)
.testContracts('notSpecial.sol', sources[5]['browser/notSpecial.sol'], ['CheckSpecials'])
.clickLaunchIcon('udapp')
.selectContract('CheckSpecials')
.waitForElementVisible('#value')
.clearValue('#value')
.setValue('#value', 0)
.createContract('')
.clickInstance(5)
.pause(1000)
.perform((done) => {
browser.getAddressAtPosition(5, (address) => {
browser.sendLowLevelTx(address, '0', '')
.pause(1000)
.waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`)
.assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `Both 'receive' and 'fallback' functions are not defined`)
.perform(done)
})
})
.end()
},
tearDown: sauce
Expand Down Expand Up @@ -199,5 +248,14 @@ var sources = [
}
`
}
},
{
'browser/notSpecial.sol': {
content: `
contract CheckSpecials {
function otherFallback() payable external {}
}
`
}
}
]