Skip to content

Commit 016588a

Browse files
authored
Merge pull request #538 from onflow/add-tests-for-arch-calls
Add test cases utilizing Cadence arch calls
2 parents 673a099 + ef02df1 commit 016588a

8 files changed

+226
-35
lines changed

tests/fixtures/storage.byte

+1-1
Large diffs are not rendered by default.

tests/fixtures/storage.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,17 @@ contract Storage {
8686
return output;
8787
}
8888

89-
function verifyArchCallToFlowBlockHeight(uint64 expected) public view returns (uint64){
89+
function verifyArchCallToFlowBlockHeight() public view returns (uint64){
9090
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()"));
9191
require(ok, "unsuccessful call to arch ");
9292
uint64 output = abi.decode(data, (uint64));
93-
require(expected == output, "output doesnt match the expected value");
9493
return output;
9594
}
9695

97-
function verifyArchCallToVerifyCOAOwnershipProof(bool expected, address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
96+
function verifyArchCallToVerifyCOAOwnershipProof(address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
9897
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("verifyCOAOwnershipProof(address,bytes32,bytes)", arg0, arg1, arg2));
9998
require(ok, "unsuccessful call to arch");
10099
bool output = abi.decode(data, (bool));
101-
require(expected == output, "output doesnt match the expected value");
102100
return output;
103101
}
104-
}
102+
}

tests/fixtures/storageABI.json

+1-12
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,7 @@
252252
"type": "function"
253253
},
254254
{
255-
"inputs": [
256-
{
257-
"internalType": "uint64",
258-
"name": "expected",
259-
"type": "uint64"
260-
}
261-
],
255+
"inputs": [],
262256
"name": "verifyArchCallToFlowBlockHeight",
263257
"outputs": [
264258
{
@@ -304,11 +298,6 @@
304298
},
305299
{
306300
"inputs": [
307-
{
308-
"internalType": "bool",
309-
"name": "expected",
310-
"type": "bool"
311-
},
312301
{
313302
"internalType": "address",
314303
"name": "arg0",

tests/helpers.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ func setupTestAccounts(emu emulator.Emulator) error {
211211
code := `
212212
transaction(eoaAddress: [UInt8; 20]) {
213213
let fundVault: @FlowToken.Vault
214-
let auth: auth(Storage) &Account
214+
let auth: auth(Capabilities, Storage) &Account
215215
216-
prepare(signer: auth(Storage) &Account) {
216+
prepare(signer: auth(Capabilities, Storage) &Account) {
217217
let vaultRef = signer.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(
218218
from: /storage/flowTokenVault
219219
) ?? panic("Could not borrow reference to the owner's Vault!")
@@ -234,7 +234,13 @@ func setupTestAccounts(emu emulator.Emulator) error {
234234
value: EVM.Balance(attoflow: weiAmount)
235235
)
236236
237-
self.auth.storage.save<@EVM.CadenceOwnedAccount>(<-account, to: StoragePath(identifier: "evm")!)
237+
self.auth.storage.save<@EVM.CadenceOwnedAccount>(
238+
<-account,
239+
to: /storage/evm
240+
)
241+
242+
let cap = self.auth.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(/storage/evm)
243+
self.auth.capabilities.publish(cap, at: /public/evm)
238244
}
239245
}`
240246

tests/web3js/build_evm_state_test.js

+200-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,21 @@ it('should handle a large number of EVM interactions', async () => {
4141
let senderBalance = await web3.eth.getBalance(conf.eoa.address)
4242
assert.equal(senderBalance, 1999999999937000000n)
4343

44+
latest = await web3.eth.getBlockNumber()
45+
assert.equal(latest, 22n)
46+
47+
// Add some calls to test historic heights, for balance and nonce
48+
let randomEOA = randomItem(accounts)
49+
50+
let randomEOABalance = await web3.eth.getBalance(randomEOA.address, 2n)
51+
assert.equal(randomEOABalance, 0n)
52+
53+
randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
54+
assert.equal(randomEOABalance, 150000000000000000n)
55+
56+
let randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, 2n)
57+
assert.equal(randomEOANonce, 0n)
58+
4459
// Each EOA has a 0.15 ether, so the below transfer amounts
4560
// should never add up to that, or the transfer transaction
4661
// will revert.
@@ -50,6 +65,10 @@ it('should handle a large number of EVM interactions', async () => {
5065

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

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

92+
// Add some calls to test historic heights, for balance and nonce
93+
randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
94+
assert.isTrue(randomEOABalance < 150000000000000000n)
95+
96+
randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, latest)
97+
assert.equal(randomEOANonce, 3n)
98+
99+
let contractAddress = null
100+
let deployed = null
73101
for (let i = 0; i < eoaCount; i++) {
74102
let sender = accounts[i]
75103

76-
let deployed = await helpers.deployContractFrom(sender, 'storage')
77-
let contractAddress = deployed.receipt.contractAddress
104+
deployed = await helpers.deployContractFrom(sender, 'storage')
105+
contractAddress = deployed.receipt.contractAddress
78106

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

109137
latest = await web3.eth.getBlockNumber()
110138
assert.equal(latest, 142n)
139+
140+
// Add calls to verify correctness of eth_estimateGas on historical heights
141+
let storeData = deployed.contract.methods.store(0).encodeABI()
142+
let estimatedGas = await web3.eth.estimateGas({
143+
from: conf.eoa.address,
144+
to: contractAddress,
145+
data: storeData,
146+
gas: 55_000,
147+
gasPrice: conf.minGasPrice
148+
}, 82n)
149+
assert.equal(estimatedGas, 23823n)
150+
151+
estimatedGas = await web3.eth.estimateGas({
152+
from: conf.eoa.address,
153+
to: contractAddress,
154+
data: storeData,
155+
gas: 55_000,
156+
gasPrice: conf.minGasPrice
157+
}, latest)
158+
assert.equal(estimatedGas, 29292n)
159+
160+
// Add calls to verify correctness of eth_getCode on historical heights
161+
let code = await web3.eth.getCode(contractAddress, 82n)
162+
assert.equal(code, '0x')
163+
164+
code = await web3.eth.getCode(contractAddress, latest)
165+
assert.lengthOf(code, 9806)
166+
167+
// Add calls to verify correctness of eth_call on historical heights
168+
let callRetrieve = await deployed.contract.methods.retrieve().encodeABI()
169+
let result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, 82n)
170+
assert.equal(result, '0x')
171+
172+
result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, latest)
173+
let storedNumber = web3.eth.abi.decodeParameter('uint256', result)
174+
assert.isTrue(storedNumber != 1337n) // this is the initial value
175+
176+
// submit a transaction that calls blockNumber()
177+
let blockNumberData = deployed.contract.methods.blockNumber().encodeABI()
178+
let res = await helpers.signAndSend({
179+
from: conf.eoa.address,
180+
to: contractAddress,
181+
data: blockNumberData,
182+
value: '0',
183+
gasPrice: conf.minGasPrice,
184+
})
185+
assert.equal(res.receipt.status, conf.successStatus)
186+
187+
// submit a transaction that calls blockTime()
188+
let blockTimeData = deployed.contract.methods.blockNumber().encodeABI()
189+
res = await helpers.signAndSend({
190+
from: conf.eoa.address,
191+
to: contractAddress,
192+
data: blockTimeData,
193+
value: '0',
194+
gasPrice: conf.minGasPrice,
195+
})
196+
assert.equal(res.receipt.status, conf.successStatus)
197+
198+
// submit a transaction that calls blockHash(uint num)
199+
let blockHashData = deployed.contract.methods.blockHash(110).encodeABI()
200+
res = await helpers.signAndSend({
201+
from: conf.eoa.address,
202+
to: contractAddress,
203+
data: blockHashData,
204+
value: '0',
205+
gasPrice: conf.minGasPrice,
206+
})
207+
assert.equal(res.receipt.status, conf.successStatus)
208+
209+
// submit a transaction that calls random()
210+
let randomData = deployed.contract.methods.random().encodeABI()
211+
res = await helpers.signAndSend({
212+
from: conf.eoa.address,
213+
to: contractAddress,
214+
data: randomData,
215+
value: '0',
216+
gasPrice: conf.minGasPrice,
217+
})
218+
assert.equal(res.receipt.status, conf.successStatus)
219+
220+
// submit a transaction that calls chainID()
221+
let chainIDData = deployed.contract.methods.chainID().encodeABI()
222+
res = await helpers.signAndSend({
223+
from: conf.eoa.address,
224+
to: contractAddress,
225+
data: chainIDData,
226+
value: '0',
227+
gasPrice: conf.minGasPrice,
228+
})
229+
assert.equal(res.receipt.status, conf.successStatus)
230+
231+
// submit a transaction that calls verifyArchCallToRandomSource(uint64 height)
232+
let getRandomSourceData = deployed.contract.methods.verifyArchCallToRandomSource(120).encodeABI()
233+
res = await helpers.signAndSend({
234+
from: conf.eoa.address,
235+
to: contractAddress,
236+
data: getRandomSourceData,
237+
value: '0',
238+
gasPrice: conf.minGasPrice,
239+
})
240+
assert.equal(res.receipt.status, conf.successStatus)
241+
242+
// make a contract call for verifyArchCallToRandomSource(uint64 height)
243+
res = await web3.eth.call({ to: contractAddress, data: getRandomSourceData }, latest)
244+
assert.notEqual(
245+
res,
246+
'0x0000000000000000000000000000000000000000000000000000000000000000'
247+
)
248+
assert.lengthOf(res, 66)
249+
250+
// submit a transaction that calls verifyArchCallToRevertibleRandom()
251+
let revertibleRandomData = deployed.contract.methods.verifyArchCallToRevertibleRandom().encodeABI()
252+
res = await helpers.signAndSend({
253+
from: conf.eoa.address,
254+
to: contractAddress,
255+
data: revertibleRandomData,
256+
value: '0',
257+
gasPrice: conf.minGasPrice,
258+
})
259+
assert.equal(res.receipt.status, conf.successStatus)
260+
261+
// make a contract call for verifyArchCallToRevertibleRandom()
262+
res = await web3.eth.call({ to: contractAddress, data: revertibleRandomData }, latest)
263+
assert.notEqual(
264+
res,
265+
'0x0000000000000000000000000000000000000000000000000000000000000000'
266+
)
267+
assert.lengthOf(res, 66)
268+
269+
// submit a transaction that calls verifyArchCallToFlowBlockHeight()
270+
let flowBlockHeightData = deployed.contract.methods.verifyArchCallToFlowBlockHeight().encodeABI()
271+
res = await helpers.signAndSend({
272+
from: conf.eoa.address,
273+
to: contractAddress,
274+
data: flowBlockHeightData,
275+
value: '0',
276+
gasPrice: conf.minGasPrice,
277+
})
278+
assert.equal(res.receipt.status, conf.successStatus)
279+
280+
// make a contract call for verifyArchCallToFlowBlockHeight()
281+
res = await web3.eth.call({ to: contractAddress, data: flowBlockHeightData }, latest)
282+
assert.equal(
283+
web3.eth.abi.decodeParameter('uint64', res),
284+
latest,
285+
)
286+
287+
// submit a transaction that calls verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
288+
let tx = await web3.eth.getTransactionFromBlock(conf.startBlockHeight, 1)
289+
let verifyCOAOwnershipProofData = deployed.contract.methods.verifyArchCallToVerifyCOAOwnershipProof(
290+
tx.to,
291+
'0x1bacdb569847f31ade07e83d6bb7cefba2b9290b35d5c2964663215e73519cff',
292+
web3.utils.hexToBytes('f853c18088f8d6e0586b0a20c78365766df842b840b90448f4591df2639873be2914c5560149318b7e2fcf160f7bb8ed13cfd97be2f54e6889606f18e50b2c37308386f840e03a9fff915f57b2164cba27f0206a95')
293+
).encodeABI()
294+
res = await helpers.signAndSend({
295+
from: conf.eoa.address,
296+
to: contractAddress,
297+
data: verifyCOAOwnershipProofData,
298+
value: '0',
299+
gasPrice: conf.minGasPrice,
300+
})
301+
assert.equal(res.receipt.status, conf.successStatus)
302+
303+
// make a contract call for verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
304+
res = await web3.eth.call({ to: contractAddress, data: verifyCOAOwnershipProofData }, latest)
305+
assert.equal(
306+
web3.eth.abi.decodeParameter('bool', res),
307+
false,
308+
)
111309
})
112310

113311
function randomItem(items) {

tests/web3js/eth_deploy_contract_and_interact_test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ it('deploy contract and interact', async () => {
1818
assert.equal(rcp.contractAddress, contractAddress)
1919
assert.equal(rcp.status, conf.successStatus)
2020
assert.isUndefined(rcp.to)
21-
assert.equal(rcp.gasUsed, 1207193n)
21+
assert.equal(rcp.gasUsed, 1130512n)
2222
assert.equal(rcp.gasUsed, rcp.cumulativeGasUsed)
2323

2424
// check if latest block contains the deploy results
@@ -233,6 +233,6 @@ it('deploy contract and interact', async () => {
233233
},
234234
'latest'
235235
)
236-
assert.equal(gasEstimate, 27442n)
236+
assert.equal(gasEstimate, 27398n)
237237

238238
})

tests/web3js/eth_filter_endpoints_test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ describe('eth_getFilterChanges', async () => {
345345
assert.equal(txHashes[0], res.receipt.transactionHash)
346346
assert.equal(
347347
txHashes[1],
348-
'0x9584d4f066928b8a4bf0699e3375bae4fa95adfd250b46551a40043d47599b93'
348+
'0xb1b9deb629374d7c6df6becb7011282c8b733922b664a74ea9cd5bcb333d193e'
349349
)
350350
})
351351

@@ -398,12 +398,12 @@ describe('eth_getFilterChanges', async () => {
398398
from: '0x0000000000000000000000030000000000000000',
399399
gas: '0x5b04',
400400
gasPrice: '0x0',
401-
hash: '0xf87ca437004ffa783d7775b9d07f143f851879be4bcc0d66b983b8dd3b96605b',
401+
hash: '0x71201dbf66271cedb6e87a5364b2cb84f6170e282f2b3f676196687bdf4babe0',
402402
input: '0x',
403403
nonce: '0x9',
404404
to: '0x658Bdf435d810C91414eC09147DAA6DB62406379',
405405
transactionIndex: '0x1',
406-
value: '0x38a978',
406+
value: '0x388fb0',
407407
type: '0x0',
408408
chainId: '0x286',
409409
v: '0xff',

0 commit comments

Comments
 (0)