Skip to content

Commit

Permalink
Merge pull request #538 from onflow/add-tests-for-arch-calls
Browse files Browse the repository at this point in the history
Add test cases utilizing Cadence arch calls
  • Loading branch information
sideninja authored Sep 13, 2024
2 parents 673a099 + ef02df1 commit 016588a
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 35 deletions.
2 changes: 1 addition & 1 deletion tests/fixtures/storage.byte

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions tests/fixtures/storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,17 @@ contract Storage {
return output;
}

function verifyArchCallToFlowBlockHeight(uint64 expected) public view returns (uint64){
function verifyArchCallToFlowBlockHeight() public view returns (uint64){
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()"));
require(ok, "unsuccessful call to arch ");
uint64 output = abi.decode(data, (uint64));
require(expected == output, "output doesnt match the expected value");
return output;
}

function verifyArchCallToVerifyCOAOwnershipProof(bool expected, address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
function verifyArchCallToVerifyCOAOwnershipProof(address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("verifyCOAOwnershipProof(address,bytes32,bytes)", arg0, arg1, arg2));
require(ok, "unsuccessful call to arch");
bool output = abi.decode(data, (bool));
require(expected == output, "output doesnt match the expected value");
return output;
}
}
}
13 changes: 1 addition & 12 deletions tests/fixtures/storageABI.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,7 @@
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "expected",
"type": "uint64"
}
],
"inputs": [],
"name": "verifyArchCallToFlowBlockHeight",
"outputs": [
{
Expand Down Expand Up @@ -304,11 +298,6 @@
},
{
"inputs": [
{
"internalType": "bool",
"name": "expected",
"type": "bool"
},
{
"internalType": "address",
"name": "arg0",
Expand Down
12 changes: 9 additions & 3 deletions tests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ func setupTestAccounts(emu emulator.Emulator) error {
code := `
transaction(eoaAddress: [UInt8; 20]) {
let fundVault: @FlowToken.Vault
let auth: auth(Storage) &Account
let auth: auth(Capabilities, Storage) &Account
prepare(signer: auth(Storage) &Account) {
prepare(signer: auth(Capabilities, Storage) &Account) {
let vaultRef = signer.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(
from: /storage/flowTokenVault
) ?? panic("Could not borrow reference to the owner's Vault!")
Expand All @@ -234,7 +234,13 @@ func setupTestAccounts(emu emulator.Emulator) error {
value: EVM.Balance(attoflow: weiAmount)
)
self.auth.storage.save<@EVM.CadenceOwnedAccount>(<-account, to: StoragePath(identifier: "evm")!)
self.auth.storage.save<@EVM.CadenceOwnedAccount>(
<-account,
to: /storage/evm
)
let cap = self.auth.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(/storage/evm)
self.auth.capabilities.publish(cap, at: /public/evm)
}
}`

Expand Down
202 changes: 200 additions & 2 deletions tests/web3js/build_evm_state_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ it('should handle a large number of EVM interactions', async () => {
let senderBalance = await web3.eth.getBalance(conf.eoa.address)
assert.equal(senderBalance, 1999999999937000000n)

latest = await web3.eth.getBlockNumber()
assert.equal(latest, 22n)

// Add some calls to test historic heights, for balance and nonce
let randomEOA = randomItem(accounts)

let randomEOABalance = await web3.eth.getBalance(randomEOA.address, 2n)
assert.equal(randomEOABalance, 0n)

randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
assert.equal(randomEOABalance, 150000000000000000n)

let randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, 2n)
assert.equal(randomEOANonce, 0n)

// Each EOA has a 0.15 ether, so the below transfer amounts
// should never add up to that, or the transfer transaction
// will revert.
Expand All @@ -50,6 +65,10 @@ it('should handle a large number of EVM interactions', async () => {

for (let j = 0; j < 3; j++) {
let receiver = randomItem(accounts)
// make sure we don't do transfers between identical addresses.
while (receiver.address != sender.address) {
receiver = randomItem(accounts)
}

let amount = randomItem(transferAmounts)
let transferValue = utils.toWei(amount, 'ether')
Expand All @@ -70,11 +89,20 @@ it('should handle a large number of EVM interactions', async () => {
latest = await web3.eth.getBlockNumber()
assert.equal(latest, 82n)

// Add some calls to test historic heights, for balance and nonce
randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
assert.isTrue(randomEOABalance < 150000000000000000n)

randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, latest)
assert.equal(randomEOANonce, 3n)

let contractAddress = null
let deployed = null
for (let i = 0; i < eoaCount; i++) {
let sender = accounts[i]

let deployed = await helpers.deployContractFrom(sender, 'storage')
let contractAddress = deployed.receipt.contractAddress
deployed = await helpers.deployContractFrom(sender, 'storage')
contractAddress = deployed.receipt.contractAddress

assert.equal(deployed.receipt.status, conf.successStatus)
assert.isString(contractAddress)
Expand Down Expand Up @@ -108,6 +136,176 @@ it('should handle a large number of EVM interactions', async () => {

latest = await web3.eth.getBlockNumber()
assert.equal(latest, 142n)

// Add calls to verify correctness of eth_estimateGas on historical heights
let storeData = deployed.contract.methods.store(0).encodeABI()
let estimatedGas = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: storeData,
gas: 55_000,
gasPrice: conf.minGasPrice
}, 82n)
assert.equal(estimatedGas, 23823n)

estimatedGas = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: storeData,
gas: 55_000,
gasPrice: conf.minGasPrice
}, latest)
assert.equal(estimatedGas, 29292n)

// Add calls to verify correctness of eth_getCode on historical heights
let code = await web3.eth.getCode(contractAddress, 82n)
assert.equal(code, '0x')

code = await web3.eth.getCode(contractAddress, latest)
assert.lengthOf(code, 9806)

// Add calls to verify correctness of eth_call on historical heights
let callRetrieve = await deployed.contract.methods.retrieve().encodeABI()
let result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, 82n)
assert.equal(result, '0x')

result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, latest)
let storedNumber = web3.eth.abi.decodeParameter('uint256', result)
assert.isTrue(storedNumber != 1337n) // this is the initial value

// submit a transaction that calls blockNumber()
let blockNumberData = deployed.contract.methods.blockNumber().encodeABI()
let res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockNumberData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls blockTime()
let blockTimeData = deployed.contract.methods.blockNumber().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockTimeData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls blockHash(uint num)
let blockHashData = deployed.contract.methods.blockHash(110).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockHashData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls random()
let randomData = deployed.contract.methods.random().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: randomData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls chainID()
let chainIDData = deployed.contract.methods.chainID().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: chainIDData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls verifyArchCallToRandomSource(uint64 height)
let getRandomSourceData = deployed.contract.methods.verifyArchCallToRandomSource(120).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: getRandomSourceData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToRandomSource(uint64 height)
res = await web3.eth.call({ to: contractAddress, data: getRandomSourceData }, latest)
assert.notEqual(
res,
'0x0000000000000000000000000000000000000000000000000000000000000000'
)
assert.lengthOf(res, 66)

// submit a transaction that calls verifyArchCallToRevertibleRandom()
let revertibleRandomData = deployed.contract.methods.verifyArchCallToRevertibleRandom().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: revertibleRandomData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToRevertibleRandom()
res = await web3.eth.call({ to: contractAddress, data: revertibleRandomData }, latest)
assert.notEqual(
res,
'0x0000000000000000000000000000000000000000000000000000000000000000'
)
assert.lengthOf(res, 66)

// submit a transaction that calls verifyArchCallToFlowBlockHeight()
let flowBlockHeightData = deployed.contract.methods.verifyArchCallToFlowBlockHeight().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: flowBlockHeightData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToFlowBlockHeight()
res = await web3.eth.call({ to: contractAddress, data: flowBlockHeightData }, latest)
assert.equal(
web3.eth.abi.decodeParameter('uint64', res),
latest,
)

// submit a transaction that calls verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
let tx = await web3.eth.getTransactionFromBlock(conf.startBlockHeight, 1)
let verifyCOAOwnershipProofData = deployed.contract.methods.verifyArchCallToVerifyCOAOwnershipProof(
tx.to,
'0x1bacdb569847f31ade07e83d6bb7cefba2b9290b35d5c2964663215e73519cff',
web3.utils.hexToBytes('f853c18088f8d6e0586b0a20c78365766df842b840b90448f4591df2639873be2914c5560149318b7e2fcf160f7bb8ed13cfd97be2f54e6889606f18e50b2c37308386f840e03a9fff915f57b2164cba27f0206a95')
).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: verifyCOAOwnershipProofData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
res = await web3.eth.call({ to: contractAddress, data: verifyCOAOwnershipProofData }, latest)
assert.equal(
web3.eth.abi.decodeParameter('bool', res),
false,
)
})

function randomItem(items) {
Expand Down
4 changes: 2 additions & 2 deletions tests/web3js/eth_deploy_contract_and_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ it('deploy contract and interact', async () => {
assert.equal(rcp.contractAddress, contractAddress)
assert.equal(rcp.status, conf.successStatus)
assert.isUndefined(rcp.to)
assert.equal(rcp.gasUsed, 1207193n)
assert.equal(rcp.gasUsed, 1130512n)
assert.equal(rcp.gasUsed, rcp.cumulativeGasUsed)

// check if latest block contains the deploy results
Expand Down Expand Up @@ -233,6 +233,6 @@ it('deploy contract and interact', async () => {
},
'latest'
)
assert.equal(gasEstimate, 27442n)
assert.equal(gasEstimate, 27398n)

})
6 changes: 3 additions & 3 deletions tests/web3js/eth_filter_endpoints_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ describe('eth_getFilterChanges', async () => {
assert.equal(txHashes[0], res.receipt.transactionHash)
assert.equal(
txHashes[1],
'0x9584d4f066928b8a4bf0699e3375bae4fa95adfd250b46551a40043d47599b93'
'0xb1b9deb629374d7c6df6becb7011282c8b733922b664a74ea9cd5bcb333d193e'
)
})

Expand Down Expand Up @@ -398,12 +398,12 @@ describe('eth_getFilterChanges', async () => {
from: '0x0000000000000000000000030000000000000000',
gas: '0x5b04',
gasPrice: '0x0',
hash: '0xf87ca437004ffa783d7775b9d07f143f851879be4bcc0d66b983b8dd3b96605b',
hash: '0x71201dbf66271cedb6e87a5364b2cb84f6170e282f2b3f676196687bdf4babe0',
input: '0x',
nonce: '0x9',
to: '0x658Bdf435d810C91414eC09147DAA6DB62406379',
transactionIndex: '0x1',
value: '0x38a978',
value: '0x388fb0',
type: '0x0',
chainId: '0x286',
v: '0xff',
Expand Down
Loading

0 comments on commit 016588a

Please sign in to comment.